如何禁用 JavaScript 中的重复按键

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17514798/
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-10-27 08:36:35  来源:igfitidea点击:

How to disable repetitive keydown in JavaScript

javascriptkeydown

提问by Novak

I have a same problem like this guy How to disable repetitive keydown in jQuery, it's just that I'm not using jQuery so I'm having hard time translating it to "pure" JavaScript, anyways I have set switch-case of some keys and when I press and hold right arrow key my div is flying. Also if it's not a problem can you tell me what would be the easiest way to stop div movement when I let the right arrow key go, do I have to make a new switch case with clearIntervalor?

我有一个和这个人一样的问题如何在 jQuery 中禁用重复按键,只是我没有使用 jQuery,所以我很难将它转换为“纯”JavaScript,无论如何我已经设置switch了一些键的大小写和当我按住右箭头键时,我的 div 正在飞行。另外,如果这不是问题,你能告诉我当我放开右箭头键时停止 div 移动的最简单方法是什么,我是否必须用clearInterval或制作一个新的开关盒?

switch (keyPressed) {
    case 39:
        setInterval(movFwr, 50);
        break;
}

function movFwr() {
    if (currPos == 1000) {
        a.style.left = 1000 + "px";
    } else currPos += 10;
    a.style.left = trenutnaPozicija + "px";
}

I'm sorry guys, I've been busy a bit, I'm testing all possibilities and so far I have seen some interesting suggestions. I'll test em all these days and then rate of what ever is that you do on this site. Great community I must say. Thank you all for your help :)

对不起各位,我有点忙,我正在测试所有的可能性,到目前为止我看到了一些有趣的建议。这些天我会测试它们,然后评估你在这个网站上所做的一切。我必须说,伟大的社区。谢谢大家的帮助 :)

回答by yckart

Something like this should do the trick;

像这样的事情应该可以解决问题;

var down = false;
document.addEventListener('keydown', function () {
    if(down) return;
    down = true;

    // your magic code here
}, false);

document.addEventListener('keyup', function () {
    down = false;
}, false);

回答by Paul S.

I would record the time and prevent action unless enough time has passed, for example using Date.now

我会记录时间并防止采取行动,除非经过足够的时间,例如使用 Date.now

var lastPress = 0;

function myListener() {
    var now = Date.now();
    if (now - lastPress < 1000) return; // less than a second ago, stop
    lastPress = now;
    // continue..
}


This can be made into a more generic function

这可以做成一个更通用的函数

function restrict(func, minDuration) {
    var lastPress = 0;
    return function () {
        var now = Date.now();
        if (now - lastPress < minDuration) return; // or `throw`
        lastPress = now;
        return func.apply(this, arguments);
    };
}
// now, for example
foo = function () {console.log('foo');};
bar = restrict(foo, 200); // only permit up to once every 200ms
bar(); // logs "foo"
bar(); // void as less than 200ms passed

回答by gilly3

To ignore key events caused by key repeats, keep track of which keys are pressed during the keydownand keyupevents.

要忽略由键重复引起的键事件,请跟踪在keydownkeyup事件期间按下了哪些键。

var pressedKeys = [];
function keydownHandler(e) {
    var isRepeating = !!pressedKeys[e.keyCode];
    pressedKeys[e.keyCode] = true;
    switch (e.keyCode) {
        case !isRepeating && 39:
            // do something when the right arrow key is pressed, but not repeating
            break;
    }
}
function keyupHandler(e) {
    pressedkeys[e.keyCode] = false;
}

To stop your div moving, you could keep track of the interval ids in an array, and clear the interval during the keyupevent with something like clearInterval(intervalIds[e.keyCode]), but I'd probably switch to using setTimeout()and checking whether they key is down instead. That way, you don't have to keep track of another variable.

要停止您的 div 移动,您可以跟踪数组中的间隔 id,并在keyup事件期间使用类似的内容清除间隔clearInterval(intervalIds[e.keyCode]),但我可能会转而使用setTimeout()并检查它们的键是否按下。这样,您就不必跟踪另一个变量。

var pressedKeys = [];
function keydownHandler(e) {
    var isRepeating = !!pressedKeys[e.keyCode];
    pressedKeys[e.keyCode] = true;
    switch (e.keyCode) {
        case !isRepeating && 39:
            movFwr();
            break;
    }
}
function keyupHandler(e) {
    pressedkeys[e.keyCode] = false;
}
function movFwr() {
    if (pressedKeys[39] && currPos < 1000) {
        currPos += 10;
        a.style.left = currPos + "px";
        setTimeout(movFwr, 50);
    }
}

This way, you also automatically stop repeating the function as soon as the div reaches the right edge, instead of waiting for the user to release the arrow key.

这样,您还可以在 div 到达右边缘时自动停止重复该功能,而不是等待用户释放箭头键。

回答by Patrick Evans

Track the last key pressed, if its the same as current ignore it by returning, and use clearIntervalto stop the intervals

跟踪上次按下的键,如果与当前键相同则返回忽略它,并用于clearInterval停止间隔

//global variables
var lastKey = 0;
var moveTimer = [];

//in keydown function
if(lastKey == keyPressed)
    return;
switch (keyPressed) {
    case 39:
        lastKey = keyPressed
        moveTimer[keyPressed] = setInterval(movFwr, 50);
        break;
}


//in a onkey up function
lastKey = null;
if(typeof(moveTimer[keyPressed]) != "undefined")
    clearInterval(moveTimer[keyPressed]);