如何避免 JavaScript 中自动重复的按键事件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7686197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 03:10:54  来源:igfitidea点击:

How can I avoid autorepeated keydown events in JavaScript?

javascriptjquerykeyboard

提问by agente_secreto

If the user holds down the key, multiple keydown events are fired. For usability reasons I need to use keydown, not keyup, but I want to avoid this situation. My relevant code is the following:

如果用户按住该键,则会触发多个 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;
        }     
      });

So when the user holds down the down key, for example, goDown() is fired multiple times. I would like it to fire just once even if the user holds the key down.

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

回答by 4esn0k

Use event.repeatto detect whether or not the event is repeating. You could then wait for "keyup" before allowing the handler to execute a second time.

使用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;
});

回答by mattybrad

Another simple adjustment to the accepted answer to allow for the multiple keys scenario:

对已接受答案的另一个简单调整以允许多键场景:

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 = {};
});

回答by sergzach

So, if the existing solution seems dubious (it doesn't consider the case when 2 or more buttons is pressed simultaneously), I suggest another solution that takes it into account.

因此,如果现有解决方案看起来可疑(它不考虑同时按下 2 个或更多按钮的情况),我建议另一种解决方案将其考虑在内。

The _prevKeyDownobject is to store keys that are currently pressed.

_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 );
    }

回答by Juan Tomas

(Copied from another question which turned out to be a duplicate of this one.)

(从另一个问题复制,结果证明是这个问题的副本。)

dmaurolizer's KeyPress librarygives fine control over all keyboard events. You provide callback functions for events. The keydownevent sends an optional isRepeatparam so you can ignore auto-repeats. Here's a sample using that functionality for the thrust control in a video game:

dmaurolizer 的KeyPress 库可以很好地控制所有键盘事件。您为事件提供回调函数。该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;
        }
    }
]);