如何在Angularjs中观察按键组合?

如何在Angularjs中观察按键组合?,angularjs,keypress,Angularjs,Keypress,我正试着让我的控制器监视按键组合。为了便于讨论,让我们说:上下左右b a。无论用户当前在页面中的哪个位置,我如何才能有角度来查看这些内容?看起来您可以使用 这是一本书 对于这个示例,我只是将ng keydown绑定到。可以很好地捕获全局所有键盘事件 正如@charlietfl指出的,ng keydown注册了大量键盘事件,因此要使其可用需要大量工作。例如,如果您尝试侦听组合(如ctrl+r),则ctrl键将注册多次 JS: var myApp = angular.module('myApp',

我正试着让我的控制器监视按键组合。为了便于讨论,让我们说:上下左右b a。无论用户当前在页面中的哪个位置,我如何才能有角度来查看这些内容?

看起来您可以使用

这是一本书

对于这个示例,我只是将
ng keydown
绑定到
。可以很好地捕获全局所有键盘事件

正如@charlietfl指出的,
ng keydown
注册了大量键盘事件,因此要使其可用需要大量工作。例如,如果您尝试侦听组合(如
ctrl
+
r
),则
ctrl
键将注册多次

JS:

var myApp = angular.module('myApp', []);

myApp.controller('Ctrl', function($scope) {


    $scope.keyBuffer = [];

    function arrays_equal(a,b) { return !(a<b || b<a); }

    $scope.down = function(e) {

      $scope.keyBuffer.push(e.keyCode);

      var upUp = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65];
      if (arrays_equal(upUp, $scope.keyBuffer)) {

        alert('thats it!');
      }
    };

  });
<body ng-controller="Ctrl" ng-keydown="down($event)">
(function () {

  'use strict';
  var lastKey = 0;
  //var commondKey = 17;
  var commondKey = 91;
  angular
    .module('xinshu')
    .directive('saveEnter', function () {
      return function (scope, element, attrs) {
        element.bind("keydown", function (event) {
          if (event.which != commondKey && event.which != 83) {
            lastKey = 0;
          }
          if (lastKey == commondKey && event.which == 83) {
            scope.$apply(function () {
              scope.$eval(attrs.saveEnter);
            });
            event.preventDefault();
          }
          lastKey = event.which;
        });
      };
    });
})();
<input id="title" save-enter="vm.saveTitle()"/>
var myApp=angular.module('myApp',[]);
myApp.controller('Ctrl',函数($scope){
$scope.keyBuffer=[];

函数数组_equal(a,b){return!(a这都是未经测试的,但是您可以使用

在输入字段之外,我认为ng按键不起作用,但来自的按键可能会起作用

我确信也应该有一个数组diff函数,但我现在无法调用特定的调用。

请检查。我已经实现了一个简单的“连续两次上击键”场景

您可以在普通jQuery中执行此操作,并使用
$rootScope.$broadcast
与事件通信

在和Angular
run
回调中注册jQuery代码(保证Angular已经启动):

然后任何控制器都可以监听此事件,如:

$scope.$on('DoubleUpFired', function() {
    $scope.fired = true;
});
ng keydown
操作回调绑定到
body
是可以的,但有一个小缺点。它会在每次击键时触发一个
$digest
。您真正想要的是一个
$digest
,只有在您需要更新UI时才输入序列

编辑 请参阅有关如何删除实际jQuery依赖项的注释。

以下是我的看法:

var app = angular.module('contra', []);
app.directive('code', function () {
    function codeState() {
        this.currentState = 0;
        this.keys = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65];
        this.keyPressed = function (key) {
            if (this.keys[this.currentState] == key) {
                this.currentState++;
                if (this.currentState == this.keys.length) {
                    this.currentState = 0;
                    return true;
                }
            } else {
                this.currentState = 0;
            }
            return false;
        };
    };
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            var cs = new codeState();
            scope.isValid = "NO";
            element.bind("keydown", function (event) {
                scope.$apply(function () {
                    if (cs.keyPressed(event.which)) {
                        scope.isValid = "YES";
                        console.log("CODE ENTERED");
                    } else {
                        scope.isValid = "NO";
                    }
                });
            });
        }
    }
});
它的不同之处在于它是一个指令,所以如果你将它附加到正文上,它将应用于整个页面。这也允许多次输入代码

普朗克:


我正在用另一种方式来做

$scope.keyboard = {
  buffer: [],
  detectCombination: function() {
    var codes = {};

    this.buffer.forEach(function(code) {
      codes['key_' + code] = 1;
    });

    if ((codes.key_91 || codes.key_93) && codes.key_8) {
      // I'm looking for 'command + delete'
    }
  },
  keydown: function($event) {
    this.buffer.push($event.keyCode);
    this.detectCombination();
  },
  keyup: function($event, week) {
    this.buffer = [];
  }
};

如果您尝试使用“ctrl+s”或“commond+s”(更改commondKey)进行保存,可能可以使用类似的方式:

指令:

var myApp = angular.module('myApp', []);

myApp.controller('Ctrl', function($scope) {


    $scope.keyBuffer = [];

    function arrays_equal(a,b) { return !(a<b || b<a); }

    $scope.down = function(e) {

      $scope.keyBuffer.push(e.keyCode);

      var upUp = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65];
      if (arrays_equal(upUp, $scope.keyBuffer)) {

        alert('thats it!');
      }
    };

  });
<body ng-controller="Ctrl" ng-keydown="down($event)">
(function () {

  'use strict';
  var lastKey = 0;
  //var commondKey = 17;
  var commondKey = 91;
  angular
    .module('xinshu')
    .directive('saveEnter', function () {
      return function (scope, element, attrs) {
        element.bind("keydown", function (event) {
          if (event.which != commondKey && event.which != 83) {
            lastKey = 0;
          }
          if (lastKey == commondKey && event.which == 83) {
            scope.$apply(function () {
              scope.$eval(attrs.saveEnter);
            });
            event.preventDefault();
          }
          lastKey = event.which;
        });
      };
    });
})();
<input id="title" save-enter="vm.saveTitle()"/>
元素:

var myApp = angular.module('myApp', []);

myApp.controller('Ctrl', function($scope) {


    $scope.keyBuffer = [];

    function arrays_equal(a,b) { return !(a<b || b<a); }

    $scope.down = function(e) {

      $scope.keyBuffer.push(e.keyCode);

      var upUp = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65];
      if (arrays_equal(upUp, $scope.keyBuffer)) {

        alert('thats it!');
      }
    };

  });
<body ng-controller="Ctrl" ng-keydown="down($event)">
(function () {

  'use strict';
  var lastKey = 0;
  //var commondKey = 17;
  var commondKey = 91;
  angular
    .module('xinshu')
    .directive('saveEnter', function () {
      return function (scope, element, attrs) {
        element.bind("keydown", function (event) {
          if (event.which != commondKey && event.which != 83) {
            lastKey = 0;
          }
          if (lastKey == commondKey && event.which == 83) {
            scope.$apply(function () {
              scope.$eval(attrs.saveEnter);
            });
            event.preventDefault();
          }
          lastKey = event.which;
        });
      };
    });
})();
<input id="title" save-enter="vm.saveTitle()"/>

您可以在指令中重命名saveEnter,并更改html中的saveEnter

“vm.saveTitle()”是您想要执行的功能。

检测退格键(Mac)和删除键(PC):

。。
$scope.keyDown=函数(值){
if(value.keyCode==46 | | value.keyCode==8){
//警报(“按下删除键”);
}
};

正在玩这个游戏,但必须检查用户是否有中断,如果中断,则清空数组,在按下新键之前索引现有数组…开始花费时间bulletproof@charlietfl是的,完全正确。因为按住键时,ng keydown会重复。我到现在为止还没有检查过。可能是ng keyup
会更好吗?一旦你深入研究,会有更多的功能。这是有效的,我还添加了缓冲区功能,因此keyBuffer的长度永远不会超过Up。正如Kos Prov在本线程的不同回答中提到的,它确实有缺点,即每个按键都会调用摘要。
keypress
不会为箭头键触发如果您访问$document,只需插入它…就可以绑定到它。我喜欢这样一个事实,即它只在输入序列时调用摘要,但是有没有办法不显式使用jQuery来实现这一点?jQuery是可选的。Angular内置了一个jqLite实现。只需替换
$(document).keyup(函数(事件){…}
angular.element(document).bind('keyup',function(event){…}
老实说,甚至
$rootScope.$apply()
都是一种浪费。它会为整个范围层次结构启动一个
$digest
。您可以触发事件,并且侦听它的每个范围都可以显式调用
$digest()
。这样,只会重新呈现页面中感兴趣的部分。请查看。当然,没有人能区分这两种方式,开发者很容易忘记。plnkr有效吗?我将此添加到我的应用程序指令中,它会绑定到它,但我不知道如何启动它。当我尝试plnkr时,它只是报告没有。我做错了什么吗?这如何回答问题?OP询问按键组合如果你想用按键组合触发代码(例如
Ctrl+a
),看看这个(使用AngularJS工厂):请记住你做了
if(e.ctrlKey&&e.which==number)