2

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

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

箭头键用于移动播放器(因为只要在页面上的任何位置按下键就会触发 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,尝试按键而不是 keydown,保存按键状态以及如果按钮的按键状态仍然为真,则继续移动,但这一切都失败了to 是当 keyup 被触发时,任何积极传播的 keydown 事件都会被杀死。我已经阅读了JavaScript Madness: Keyboard Events,但我没有看到任何关于这种特定行为的信息。

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

有什么建议或意见吗?

4

3 回答 3

7

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

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

于 2011-04-30T13:01:15.557 回答
0

对于未来的读者,你可以试试这个。

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);

于 2021-10-05T14:39:48.620 回答
0

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


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);

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

于 2019-01-17T17:46:54.513 回答