如何在JavaScript中避免自动重复的keydown事件?

时间:2011-10-07 10:46:38

标签: javascript jquery keyboard

如果用户按下该键,则会触发多个keydown事件。出于可用性原因,我需要使用keydown,而不是keyup,但我想避免这种情况。我的相关代码如下:

$(document).keydown(function(e) { 
        var key = 0;


        if (e == null) { key = event.keyCode;}  
        else {  key = e.which;} 


        switch(key) {
            case config.keys.left:                
              goLeft();
              break;
            case config.keys.up:                        
              goUp();
              break;
            case config.keys.right:                     
              goRight();
              break;
            case config.keys.down:                
              goDown();
              break;
            case config.keys.action:              
              select();
              break;
        }     
      });

因此,当用户按下向下键时,goDown()会多次触发。即使用户按住键,我也希望它只触发一次。

4 个答案:

答案 0 :(得分:39)

使用event.repeat检测事件是否重复。然后,您可以在允许处理程序第二次执行之前等待“keyup”。

var allowed = true;

$(document).keydown(function(event) { 
  if (event.repeat != undefined) {
    allowed = !event.repeat;
  }
  if (!allowed) return;
  allowed = false;
  //...
});

$(document).keyup(function(e) { 
  allowed = true;
});
$(document).focus(function(e) { 
  allowed = true;
});

答案 1 :(得分:7)

对允许多键情况的接受答案的另一个简单调整:

var keyAllowed = {};

$(document).keydown(function(e) {
  if (keyAllowed [e.which] === false) return;
  keyAllowed [e.which] = false;
  // code to be executed goes here
});

$(document).keyup(function(e) { 
  keyAllowed [e.which] = true;
});

$(document).focus(function(e) { 
  keyAllowed = {};
});

答案 2 :(得分:3)

所以,如果现有的解决方案看起来很可疑(它不考虑同时按下2个或更多按钮的情况),我建议考虑另一个解决方案。

_prevKeyDown 对象用于存储当前按下的键。

    _prevKeyDown = {}

    function _downKey( event )
    {
        var wh = event.which;
        var kC = event.keyCode;

        if( _prevKeyDown[ wh ] == null )
        {
            _prevKeyDown[ wh ] = {};
        }

        _prevKeyDown[ wh ][ kC ] = true;
    };

    function _upKey( event )
    {
        var wh = event.which;
        var kC = event.keyCode;

        if( _prevKeyDown[ wh ] != null )
        {
            _prevKeyDown[ wh ][ kC ] = null;
        }               
    };

    function _isKeyDown( event )
    {
        var wh = event.which;
        var kC = event.keyCode;

        var result = false;

        if( this._prevKeyDown[ wh ] != null )
        {
            if( this._prevKeyDown[ wh ][ kC ] == true )
            {
                result = true;
            }
        }

        return result;
    }

    // now your keydown/keyup handlers
    function keydown( event )
    {
        if( !_isKeyDown( event ) )
        {
            // your once-keydown handler here
            _downKey( event );
        }    
    }

    function keyup( event )
    {
        _upKey( event );
    }

答案 3 :(得分:0)

(从另一个问题复制而来,这个问题与此问题重复。)

dmaurolizer的KeyPress library可以很好地控制所有键盘事件。您为事件提供回调函数。 keydown事件会发送一个可选的isRepeat参数,因此您可以忽略自动重复。以下是使用该功能进行视频游戏中推力控制的示例:

var my_combos = listener.register_many([
    {
        "keys"          : "up",
        "on_keydown"    : function(e, num, isRepeat) {
            if (isRepeat) return ;
            thrust = 0.1;
        },
        "on_keyup"      : function() {
            thrust = 0;
        }
    }
]);