web-dev-qa-db-ja.com

JavaScriptで自動繰り返しキーダウンイベントを回避するにはどうすればよいですか?

ユーザーがキーを押したままにすると、複数のkeydownイベントが発生します。使いやすさの理由から、キーアップではなくキーダウンを使用する必要がありますが、この状況は避けたいです。私の関連コードは次のとおりです:

$(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()が複数回起動されます。ユーザーがキーを押したままにした場合でも、1回だけ起動したいと思います。

26
agente_secreto

使用する event.repeatは、イベントが繰り返されているかどうかを検出します。その後、ハンドラーが2回実行するのを許可する前に、「キーアップ」を待つことができます。

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;
});
41
4esn0k

複数のキーのシナリオを可能にするために、受け入れられた回答に対する別の簡単な調整:

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

したがって、既存のソリューションが疑わしいと思われる場合(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
sergzach

(この質問の複製であることが判明した別の質問からコピーされます。)

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;
        }
    }
]);
0
Juan Tomas