简体   繁体   English

跨浏览器的方式,在按住键时自动重复重复按下事件

[英]Cross-browser way to get automatically repeating keydown events when key is held down

Using Javascript / jQuery, how can I get automatically repeating keydown events, or equivalent, when someone holds down a key? 使用Javascript / jQuery,当有人按住某个键时,如何自动重复按下键事件或等效操作?

What I actually want is to be able to check whether a key is down, but from other questions here it looks like that's not possible. 我真正想要的是能够检查某个键是否按下,但是从这里的其他问题来看,这似乎是不可能的。 The suggested workaround seems to be recording keydown and keyup events and then assuming the key is down if a keydown event has been recorded and no subsequent keyup. 建议的解决方法似乎是记录keydown和keyup事件,然后如果已记录keydown事件并且没有后续的keyup,则假定该键已关闭。

That solution runs into a problem in my case. 在我看来,该解决方案遇到了问题。 I am designing an online experiment. 我正在设计一个在线实验。 The user is supposed to hold down the "T" key for the entire experiment, never letting it up. 用户应在整个实验过程中按住“ T”键,不要松开。 The experiment consists of multiple trials and each trial has no access to information recorded by the previous trials. 该实验包含多个试验,每个试验都无法访问先前试验记录的信息。 So, trial 1 could record keydown for T, but trial 2 wouldn't have access to that record and thus wouldn't know whether T was down or not. 因此,试验1可以记录T的密钥按下,但是试验2无法访问该记录,因此不知道T是否被按下。

Now, if holding down the T key would produce automatically repeating keydown events for T, I would have no problem because trial 2 would just catch the next keydown event for T to come along. 现在,如果按住T键会自动为T产生重复的按键事件,那么我将没有问题,因为试验2只会捕获下一个按键事件以使T出现。 But it looks like I don't get automatically repeating keydown events from holding the key down, at least in Firefox. 但是,看来至少在Firefox中,我不会通过按住键来自动重复按键事件。 From what I can see it seems there is variation in the way different browsers handle holding a key down. 从我所看到的情况来看,不同的浏览器处理按下键的方式似乎有所不同。 What is a good cross-browser way to solve my problem? 什么是跨浏览器解决我的问题的好方法?

By the way, if it matters, I also need to be able to detect keyup and keydown events for other keys while all this is going on. 顺便说一句,如果这很重要,那么在进行所有这些操作的同时,我还需要能够检测其他键的keyup和keydown事件。

EDIT: after reading some of the comments I went back and verified that I do indeed get repeating keydown events under ordinary circumstances. 编辑:阅读了一些评论后,我回过头来验证我确实确实在通常情况下会重复发生键盘按下事件。 But I really don't get them in the specific situation in which I need them. 但是我真的没有在需要它们的特定情况下使用它们。 I've got some simple code which I think isolates the issue: 我有一些简单的代码,我认为可以解决这个问题:

<!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>

If you press a key and hold it down, then release, then press again, the behavior is as expected, ie there is a counter which increments while the key is held down, disappears when it's released, and then starts incrementing again when it's pressed again. 如果按下某个键并按住不放,然后松开,然后再次按下,则行为符合预期,即,有一个计数器,按住该键时该计数器增加,释放该键时消失,然后按下该键再次开始增加计数再次。

But if you press TWO keys down, then release ONE, I would have thought that the other (not released) key would continue sending keydown events so that the counter would (after resetting) continue incrementing. 但是,如果您按下两个键,然后释放一个,我会认为另一个(未释放)键将继续发送按键事件,以便计数器(在重置之后)继续递增。 In fact, that doesn't happen. 实际上,这不会发生。 Any idea why and how to make it happen? 知道为什么以及如何实现它吗?

In the browsers I tried this in, I got repeated keydown events when holding a typeable key down. 在我尝试使用的浏览器中,按住可键入的键时,重复出现了键按下事件。 I don't know if this is a problem you actually need to solve. 我不知道这是否是您实际上需要解决的问题。

But, if you did think you need to solve it OR if you want to control the repeat-rate yourself, you could do it like this: 但是,如果您确实认为需要解决此问题,或者如果您想自己控制重复率,则可以执行以下操作:

  1. Capture the events for keydown and keyup. 捕获事件以进行击键和击键。
  2. On keydown, set an interval timer that fires however often you want to know that the key is still down. 按下按键时,设置一个间隔计时器,该计时器会触发,但是您经常想知道按键仍在按下状态。
  3. On keyup for that key, stop the interval timer. 在键入该键时,停止间隔计时器。
  4. You will get repeated notification in a cross browser way as long as the key is held down. 只要按住该键,您将以跨浏览器的方式反复收到通知。

Working demo here: http://jsfiddle.net/jfriend00/XbZYs/ 此处的工作演示: 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;
    }
});

If you want a key to auto-repeat forever until it is raised, even if other keys are pressed and released in the meantime and you want those other keys to do their own auto-repeating, then the OS does not ipmlement that behavior so you would have to implement it yourself. 如果您希望某个键在弹出之前一直永久自动重复,即使同时按下并释放了其他键,并且您希望这些其他键执行自己的自动重复操作,则操作系统也不会执行该操作,所以您将不得不自己实施。 You can do something like this which calls a callback function for every key repeat event: 您可以执行以下操作,为每个键重复事件调用一个回调函数:

Working demo: http://jsfiddle.net/jfriend00/aD3Eg/ 工作演示: 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];
    }
});
​

The repeatCallback function is called for all of these manufactured auto-repeat events and passed the key that is auto-repeating. 对所有这些制造的自动重复事件都调用repeatCallback函数,并传递了自动重复的密钥。

看一下这个jQuery插件: fastKeys我认为,这就是您想要/需要的...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当按住箭头键时,如何在Firefox中获得自动重复的keydown事件? - How can I get auto-repeated keydown events in Firefox when arrow keys are held down? 服务器发送的事件:如何以跨浏览器的方式自动重新连接? - Server-sent events: How do you automatically reconnect in a cross-browser way? HTML Canvas:按住键时控制键按下注册表 - HTML Canvas: Controlling keydown registry when key is held down 使用 JavaScript 每次按下键时,即使它被按住,我如何才能只获取一次 keydown 事件? - How can I get keydown events only once each time the key is pressed, even if it's held down, with JavaScript? 在页面加载时绑定事件的跨浏览器兼容方式 - Cross-browser compatible way to bind events on page load 工具提示是否有跨浏览器方式? - Is there a cross-browser way for tooltips? 跨浏览器获取keyCode - Cross-browser get keyCode 真正的跨浏览器方式来获取文档高度? - Truly cross-browser way to get document height? 获得选择边界的可靠,跨浏览器方式? - reliable, cross-browser way to get selection's boundaries? 跨浏览器获取contenteditable内容的方法 - cross-browser way to get contenteditable's content
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM