当 keyup 事件(对于另一个键)被触发时,keydown(重复)会中断

发布于 2024-11-03 22:23:55 字数 2058 浏览 3 评论 0原文

这有点奇怪,所以我想我要么遗漏了一些明显的东西,要么这是这些事件在浏览器中实现方式的缺陷。

在提供一个孤立的案例之前,让我首先总结一下这个问题出现的一个示例场景;

箭头键用于移动玩家(因为只要在页面上的任何位置按下某个键,就会触发 handleKeyDown 函数)。同样,每当释放一个键时,就会触发另一个函数(handleKeyUp)。

当您(玩家)按住左键时,会重复触发handleKeyDown函数(诚然,我认为这违背了您的期望和名称的含义,但尽管如此,我确信这是所有浏览器的正常行为你知道)。

所以发生的事情是这样的:玩家持有一个方向,朝那个方向行走;然后,他们按下数字键(对于热键项目),同时按住方向继续行走。这里发生的情况是,当您释放热键项目的数字键时,玩家移动的重复就会停止!

我写了一个关于这种行为的非常小的孤立示例:

<html>
<head>
    <script type='text/javascript' src='jquery-1.5.1.min.js'></script>
    <script type='text/javascript'>
        var log = {};
        var keyState = {};
        var keyCount = {'down': 0, 'up': 0};
        window.addEventListener('keydown', handleKeyDown, false);
        window.addEventListener('keyup', handleKeyUp, false);
        function handleKeyDown (e)
            {
            keyState[e.keyCode] = true;
            keyCount.down++;
            log.prepend(" ["+e.keyCode+"] ");
            return false;
            }
        function handleKeyUp (e)
            {
            keyState[e.keyCode] = false;
            keyCount.down++;
            return true;
            }
        $(function(){log = $('#log');});
    </script>
</head>
<body>
    <div id='debug'></div>
    <div id='log'></div>
</body>

您也可以在这里尝试:

http://sikosoft.net/keys.html

按页面,您将看到 keyCode 出现在页面上。当您按住该键时,键码会一遍又一遍地重复。

当仍按住初始键时按下不同的键时,行为会变得奇怪。释放最近的键后,重复会从第一个键停止。有趣的是,如果您尝试该示例并按住一个键,然后按住第二个键,但不是释放第二个键,而是释放第一个键:第二个键确实会继续重复。

因此,似乎正在发生的事情是,当触发 keyup 事件时,它似乎会终止在较早的键上触发的 keydown 事件的重复。

我已经尝试了各种各样的事情,从在两个事件处理函数中使用返回 false、返回 true、尝试按键而不是按键、保存按键状态以及在按钮的按键状态仍然为 true 时继续移动,但这一切都归结为是当 keyup 被触发时,任何主动传播的 keydown 事件都会被终止。我已经通读了 JavaScript Madness: Keyboard Events 并且我没有看到任何关于这种特定类型的内容行为。

这是关键事件实现的设计缺陷,还是我遗漏了什么?我在 Chrome、IE 和 IE 中观察到同样的行为。火狐。

有什么建议或意见吗?

This is a bit of a weird one so I figure I'm either missing something obvious or this is a flaw with how these events are implemented in browsers.

Let me first summarize an example scenario this issue comes up with before providing an isolated case-example;

The arrow keys are used to move the player (as a handleKeyDown function is fired anytime a key is hit anywhere on the page). Likewise, anytime a key is released another function is fired (handleKeyUp).

As you (the player) hold the left key down, the handleKeyDown function is repeatedly triggered (which admittedly I think defies what you'd expect and what the name implies, but nonetheless, this is normal behavior across all browsers as I'm sure you know).

So here's what happens: the player holds a direction to walk in that direction; they then press a number key (for hot-keyed item) AS they continue to walk while holding the direction down. What happens here is that as you release the number key for the hot-keyed item, the repetition for player movement just stops!

I've written a very small isolated example of this behavior:

<html>
<head>
    <script type='text/javascript' src='jquery-1.5.1.min.js'></script>
    <script type='text/javascript'>
        var log = {};
        var keyState = {};
        var keyCount = {'down': 0, 'up': 0};
        window.addEventListener('keydown', handleKeyDown, false);
        window.addEventListener('keyup', handleKeyUp, false);
        function handleKeyDown (e)
            {
            keyState[e.keyCode] = true;
            keyCount.down++;
            log.prepend(" ["+e.keyCode+"] ");
            return false;
            }
        function handleKeyUp (e)
            {
            keyState[e.keyCode] = false;
            keyCount.down++;
            return true;
            }
        $(function(){log = $('#log');});
    </script>
</head>
<body>
    <div id='debug'></div>
    <div id='log'></div>
</body>

You can also try it here:

http://sikosoft.net/keys.html

Press any keys on the page and you will see the keyCode appear on the page. As you hold down the key, the keycode repeats over and over.

The behavior gets quirky when press down a different key while the initial key is still being held. Upon release of that recent key, the repetition stops from the first key. Interestingly, if you try the example and hold down one key, and then hold a second key, but instead of releasing the second, release the first: the second key DOES continue to repeat.

So what seems to go on is that when the keyup event is fired, it seems to terminate repetition in keydown events that were fired on an earlier key.

I've tried all sorts of things ranging from using returning false in both event-handling functions, returning true, trying keypress instead of keydown, saving key-states and continuing movement if the button's keystate is still true, but what it all comes down to is that when keyup is fired any actively propagating keydown events are killed. I've read through JavaScript Madness: Keyboard Events and I am not seeing anything about this specific sort of behavior.

Is this a design flaw with the implementation of key-events, or am I missing something? I observe this same behavior in Chrome, IE & Firefox.

Any advice or input?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风吹雪碎 2024-11-10 22:23:55

这就是操作系统/环境的工作方式,因此这也是浏览器的工作方式。

在浏览器中从另一个键按下键盘后,按键重复不应继续触发,因为它在其他地方不会出现这种情况。打开记事本、vim、pico 或您使用的任何文本编辑器,然后执行相同的事件序列。您会发现在按键后,您按下的第一个键不会继续打印新字母。这就是这些东西在操作系统中设计的方式,因此这就是它们传播到编辑器和浏览器等的方式。

That is the way the OS/environment works, and as a result that is the way the browser works.

The keydown repetition shouldn't continue firing after the keyup from another key in the browser, since it doesn't behave that way anywhere else. Open Notepad, or vim, or pico, or whatever text editor you use, and perform the same sequence of events. You'll see that after the keyup, the first key you pressed does not keep printing new letters. That's just the way these things were designed in the OS, and as a result that's the way they're propogated through to the editors and browsers etc.

£冰雨忧蓝° 2024-11-10 22:23:55

这是我的键盘输入系统。您可以在此处了解如何提取重复密钥供您自己使用。它将允许您注意到所持有的密钥,而不是像另一个错误假设的答案那样依赖操作系统。


var down = [140]; //make an array to cover all the keypresses you should need with a normal keyboard

document.addEventListener('keydown', function(event) {
  if (down[event.keyCode]){
    return;
  } else {
   //do the normal things you do when you get key presses
  down[event.keyCode]=true;
  }
}, true);
document.addEventListener('keyup', function(event) {
  down[event.keyCode]=false;
   //do the normal things you do when you get key releases
}, true);

您只需检查数组“down”以及您想要的任何键码在其中的位置。我用它来防止游戏输入中的按键重复。希望这有帮助!

Here is my system for my keyboard input. You can see how the repeating key can be extracted for your own use here. It will allow you to notice held keys and not rely on an Operating system as another answer incorrectly assumed.


var down = [140]; //make an array to cover all the keypresses you should need with a normal keyboard

document.addEventListener('keydown', function(event) {
  if (down[event.keyCode]){
    return;
  } else {
   //do the normal things you do when you get key presses
  down[event.keyCode]=true;
  }
}, true);
document.addEventListener('keyup', function(event) {
  down[event.keyCode]=false;
   //do the normal things you do when you get key releases
}, true);

You can just check for the array "down" and the position within it of whatever keycode you want. I use it to prevent keyrepeats for game input. Hope this helps!

计㈡愣 2024-11-10 22:23:55

对于未来的读者,您可以尝试一下。

let keys = {};

document.onkeydown = e => {
  if (!keys[e.code]) {
    keys[e.code] = true;
  }
};

document.onkeyup = e => (keys[e.code] = false);

move = () => {
  if (keys["ArrowLeft"]) {
    console.log("ArrowLeft")
  }
  if (keys["ArrowRight"]) {
    console.log("ArrowRight")
  }
  if (keys["ArrowDown"]) {
    console.log("ArrowDown")
  }
  if (keys["ArrowUp"]) {
    console.log("ArrowUp")
  }
};

setInterval(move, 100);

For future readers, you can try this.

let keys = {};

document.onkeydown = e => {
  if (!keys[e.code]) {
    keys[e.code] = true;
  }
};

document.onkeyup = e => (keys[e.code] = false);

move = () => {
  if (keys["ArrowLeft"]) {
    console.log("ArrowLeft")
  }
  if (keys["ArrowRight"]) {
    console.log("ArrowRight")
  }
  if (keys["ArrowDown"]) {
    console.log("ArrowDown")
  }
  if (keys["ArrowUp"]) {
    console.log("ArrowUp")
  }
};

setInterval(move, 100);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文