Как я могу избежать автоматически повторяющихся событий нажатия клавиш в JavaScript? - PullRequest
25 голосов
/ 07 октября 2011

Если пользователь удерживает клавишу, запускается несколько событий нажатия клавиши. По соображениям удобства использования мне нужно использовать 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 ]

39 голосов
/ 07 октября 2011

Используйте 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;
});
7 голосов
/ 29 октября 2013

Еще одна простая настройка принятого ответа для сценария с несколькими ключами:

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 = {};
});
3 голосов
/ 09 марта 2013

Итак, если существующее решение кажется сомнительным (оно не учитывает случай одновременного нажатия 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 );
    }
0 голосов
/ 11 августа 2016

(Скопировано из другого вопроса, который оказался дубликатом этого.)

Библиотека 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;
        }
    }
]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...