强制键控事件每个键代码仅触发一次

Force keydown event to fire only once per keyCode

本文关键字:一次 代码 事件      更新时间:2023-09-26

情况:我有一个keydown处理程序,switch按下的键,相当标准的东西,但是当按住任何键时,keydown事件会反复触发(而不是在实际按下键时仅触发一次(。

为什么这是一个问题:我想让keydown侦听器保持活动状态,即能够检测到一次按下多个键,但每keydown只触发一次事件。我想根据向下和向上之间的时间在keyup上为该keyCode做一些事情,但由于多次射击,该时间被搞砸了。

尝试过什么:我目前正在保留一个已关闭keyCodes的列表,并检查我的keydown处理程序中的那些,以防止在keyCode在我的列表中时发生默认行为。但是,该事件仍然经常触发,我担心此解决方案的效率/优雅。

实际问题:有没有一种好方法可以将keydown事件的触发限制在物理按下键时,或者只侦听特定的键代码?

在键下处理程序中,检查键是否与上次处理的键相同。如果是,请尽早退出。在键控时,忘记处理的最后一个键。

例如:

var lastEvent;
var heldKeys = {};
window.onkeydown = function(event) {
    if (lastEvent && lastEvent.keyCode == event.keyCode) {
        return;
    }
    lastEvent = event;
    heldKeys[event.keyCode] = true;
};
window.onkeyup = function(event) {
    lastEvent = null;
    delete heldKeys[event.keyCode];
};​

在此处演示(单击"结果"面板并按键(。

定义一个布尔值来记录是否按下了该键。在按键按下事件中将其设置为 true。让主循环检查值是否为 true 并处理事件,并将按下的键设置为 false。让另一个布尔值来记录密钥是否被释放(最初为 false(。如果触发键控事件,请将其设置为释放。仅当"释放"值也为 true 时,才将按键值设置为 true(在按键按下事件中(。

以下是我认为您想要实现的示例: jsFiddle 示例

目前,组合 CTRL+B 是唯一检测到的组合。只需按一些数字即可获得活动日志。当按键已按下时,它会检测保持操作。

这是一个更简洁的版本,不太容易出错。当前密钥是否是最后一个持有的密钥并不重要,因为如果 keyup 事件尚未触发,则它仍处于键关闭状态。

var heldKeys = {};
window.onkeydown = function(event) {
    if (heldKeys[event.keyCode]) {
        return;
    }
    heldKeys[event.keyCode] = true;
};
window.onkeyup = function(event) {
    heldKeys[event.keyCode] = false;
};​