我试图让用户使用箭头键在页面上移动元素。到目前为止,我的 Action 适用于上/下/左/右,但不适用于对 Angular 线(同时按下两个箭头键)。

我的听众看起来像这样:

addEventListener('keydown', function(e){
    move = false;
    x = false;
    y = false;
    var keycode;
    if (window.event) keycode = window.event.keyCode;
    else if (e) keycode = e.which;
    switch(keycode){
        case 37:
            move = true;
            x = 'negative';
            //prevent page scroll
            e.preventDefault()
        break;
        case 38:
            move = true;
            y = 'negative'
            //prevent page scroll
            e.preventDefault()
        break;
        case 39:
            move = true;
            x = 'positive'
            //prevent page scroll
            e.preventDefault()
        break;
        case 40:
            move = true;
            y = 'positive'
            //prevent page scroll
            e.preventDefault()
        break;
    }
    if(move){
        animation.move(x,y);
    }
    return false;
})

这个想法是,如果用户按下箭头键,它将xy设置为negativepositive,并触发move()函数,该函数将沿期望的方向将元素移动预设数量的像素,如果按下两个键,将触发第二个事件...我也希望能够通过快速释放和按下键来使用户似乎改变方向,但是这两个都没有发生,但是,如果用户按下另一个方向键,它们似乎除非他们完全松开琴键然后再按下另一个琴键,否则需要等一会儿动弹,直到第一个琴键被释放时,它才响应第二个琴键。

最佳答案

fiddle :http://jsfiddle.net/ATUEx/

创建一个临时缓存以记住您的按键。

处理两个键的实现将遵循此模式:

  • <keydown>
  • 清除先前的超时。
  • 检查 key 代码是否已缓存。如果是,请输入有效的组合:-删除所有缓存的键码-执行此组合的功能
    别的-删除所有缓存的键码-存储新的 key 代码-设置超时以清除键码(请参见下文),并在合理的时间内延迟
  • 重复1个

  • 合理的延迟:尝试知道哪个超时足以满足您的需要。当延迟太短时,下一个启动的事件将找不到先前输入的键控代码。

    如果延迟时间太长,则您不希望时按键会堆叠在一起。

    代码

    我创建了一个高效的函数,牢记您的代码。您应该能够很容易地实现它。
    (function(){ //Anonymous function, no leaks
        /* Change the next variable if necessary */
        var timeout = 200; /* Timeout in milliseconds*/
    
        var lastKeyCode = -1;
        var timer = null;
        function keyCheck(ev){
            var keyCode = typeof ev.which != "undefined" ? ev.which : event.keyCode;
            /* An alternative way to check keyCodes:
             * if(keyCode >= 37 && keyCode <= 40) ..*/
             /*37=Left  38=Up  39=Right  40=Down */
            if([37, 38, 39, 40].indexOf(keyCode) != -1){
    
                /* lastKeyCode == -1 = no saved key
                   Difference betwene keyCodes == opposite keys = no possible combi*/
                if(lastKeyCode == -1 || Math.abs(lastKeyCode - keyCode) == 2){
                    refresh();
                    lastKeyCode = keyCode;
                } else if(lastKeyCode == keyCode){
                    clear([lastKeyCode]);
                } else {
                    /* lastKeyCode != -1 && keyCode != lastKeyCode
                       and no opposite key = possible combi*/
                    clear([lastKeyCode, keyCode]);
                    lastKeyCode = -1
                }
                ev.preventDefault(); //Stop default behaviour
                ev.stopPropagation(); //Other event listeners won't get the event
            }
    
            /* Functions used above, grouped together for code readability */
            function reset(){
                keyCombi([lastKeyCode]);
                lastKeyCode = -1;
            }
            function clear(array_keys){
                clearTimeout(timer);
                keyCombi(array_keys);
            }
            function refresh(){
                clearTimeout(timer);
                timer = setTimeout(reset, timeout);
            }
        }
    
        var lastX = false;
        var lastY = false;
        function keyCombi(/*Array*/ keys){
            /* Are the following keyCodes in array "keys"?*/
            var left = keys.indexOf(37) != -1;
            var up = keys.indexOf(38) != -1;
            var right = keys.indexOf(39) != -1;
            var down = keys.indexOf(40) != -1;
    
            /* What direction? */
            var x = left ? "negative" : right ? "positive" : false;
            var y = up ? "negative" : down ? "positive" : false;
            /* Are we heading to a different direction?*/
            if(lastX != x || lastY != y) animation.move(x, y);
            lastX = x;
            lastY = y;
        }
    
        //Add event listener
        var eventType = "keydown";window["on"+eventType] = keyCheck;
    })();
    

    在匿名函数的末尾,添加了keydown事件监听器。此事件仅触发一次(按下键时)。当第二个键按下得足够快时,该代码会依次识别出两个键击,并调用keyCombi()

    我已将keyCombi设计为智能的,并且仅在更改值时才调用animation.move(x,y)。另外,我实现了一次处理两个方向的可能性。

    注意:我已将这些函数包含在一个匿名函数包装器中,以便不在全局(window)范围内定义变量。如果您不关心范围,请随时删除第一行和最后一行。

    关于javascript - 听多个按键,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7614340/

    10-13 07:03