5

使用 Javascript / jQuery,当有人按住某个键时,如何自动重复 keydown 事件或等效事件?

我真正想要的是能够检查一个键是否已关闭,但从这里的其他问题来看,这似乎是不可能的。建议的解决方法似乎是记录 keydown 和 keyup 事件,然后假设 keydown 事件已被记录并且没有后续 keyup。

就我而言,该解决方案遇到了问题。我正在设计一个在线实验。用户应该在整个实验过程中按住“T”键,永远不要松开。该实验由多个试验组成,每个试验都无法访问先前试验记录的信息。因此,试验 1 可以记录 T 的 keydown,但试验 2 无法访问该记录,因此不知道 T 是否关闭。

现在,如果按住 T 键会自动为 T 产生重复的 keydown 事件,我不会有任何问题,因为试验 2 只会捕获 T 的下一个 keydown 事件。但看起来我不会因为按住键而自动重复 keydown 事件,至少在 Firefox 中是这样。从我所看到的情况来看,不同浏览器处理按住键的方式似乎有所不同。什么是解决我的问题的好跨浏览器方法?

顺便说一句,如果这很重要,我还需要能够在这一切进行时检测其他键的 keyup 和 keydown 事件。

编辑:在阅读了一些评论后,我回过头来确认在正常情况下我确实会重复按键事件。但我真的没有在我需要它们的特定情况下得到它们。我有一些我认为可以隔离问题的简单代码:

<!DOCTYPE html>
<html>

<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
</head>

<body>
<div id="target"></div>
</body>

<script type="text/javascript">

var i;
function foo() {
    i++;
    $('#target').html(i);
}

function doTrial() { // do trial
    i=0;
    $(document).keydown(foo);
    $(document).keyup(endTrial);
}

function endTrial() { // end trial
    $('#target').html('');
    $(document).unbind('keydown',foo);
    $(document).unbind('keyup',endTrial);
    doTrial();
}

doTrial();

</script>

</html>

如果您按住某个键,然后松开,然后再次按下,则行为符合预期,即有一个计数器在按住键时递增,在松开时消失,然后在按下时再次开始递增再次。

但是,如果您按下两个键,然后释放一个,我会认为另一个(未释放)键会继续发送 keydown 事件,以便计数器(重置后)继续递增。事实上,这不会发生。知道为什么以及如何实现它吗?

4

2 回答 2

7

在我尝试过的浏览器中,当按住可键入的键时,我得到了重复的 keydown 事件。我不知道这是否是您真正需要解决的问题。

但是,如果你确实认为你需要解决它,或者如果你想自己控制重复率,你可以这样做:

  1. 捕获 keydown 和 keyup 的事件。
  2. 在 keydown 上,设置一个间隔计时器,无论您想知道该键是否仍处于关闭状态,该计时器都会触发。
  3. 在该键的 keyup 上,停止间隔计时器。
  4. 只要按住该键,您就会以跨浏览器的方式收到重复通知。

在这里工作演示:http: //jsfiddle.net/jfriend00/XbZYs/

var downTimer;
var lastKey;
$(document.body).keydown(function(e) {
    // if not still the same key, stop the timer
    if (e.which !== lastKey) {
        if (downTimer) {
            clearInterval(downTimer);
            downTimer = null;
        }
    }
    // remember previous key
    lastKey = e.which;
    if (!downTimer) {
        // start timer
        downTimer = setInterval(function() {
            $("#result").append("+");
        }, 125);
    }
}).keyup(function(e) {
    // stop timer
    if (downTimer) {
        clearInterval(downTimer);
        downTimer = null;
        lastKey = 0;
    }
});

如果您希望一个键永远自动重复直到它被抬起,即使同时按下并释放其他键并且您希望这些其他键进行自己的自动重复,那么操作系统不会执行该行为所以您必须自己实施。你可以做这样的事情,它为每个按键重复事件调用一个回调函数:

工作演示:http: //jsfiddle.net/jfriend00/aD3Eg/

// this is called for every manufactured repeat event
// the frequency of the repeat event is determined by the time value set
// on setInterval() below
function repeatCallback(key) {
    $("#result").append(key + " ");
}

var repeatState = {};
$(document.body).keydown(function(e) {
    var key = e.which;
    // if no time yet for this key, then start one
    if (!repeatState[key]) {
        // make copy of key code because `e` gets reused
        // by other events in IE so it won't be preserved
        repeatState[key] = setInterval(function() {
            repeatCallback(key);
        }, 125);
    } else {
        // nothing really to do here
        // The key was pressed, but there is already a timer
        // firing for it
    }
}).keyup(function(e) {
    // if we have a timer for this key, then stop it 
    // and delete it from the repeatState object
    var key = e.which;
    var timer = repeatState[key];
    if (timer) {
        clearInterval(timer);
        delete repeatState[key];
    }
});
​

对于所有这些制造的自动重复事件调用repeatCallback 函数并传递自动重复的键。​</p>

于 2012-12-25T05:11:50.160 回答
0

看看这个 jQuery 插件:我认为它是你想要/需要的fastKeys ...

于 2012-12-26T19:08:11.640 回答