[英]JavaScript KeyDown event not triggered when multiple keys are held down
[英]Prevent JavaScript keydown event from being handled multiple times while held down
我有这个代码:
else if (e.keyCode == 32){
fired = true;
在 keyDown 函数中(我添加了 document.addEventListener 代码)。 现在它工作得很好,并且完全符合我的要求。 但问题是:如果你按住这个键,它会一遍又一遍地不断地使 fire = true 直到它被释放。 我只是想让它设置 fire = true; 一次,即使按键被按下。
编辑:现在除了 Internet Explorer 之外的所有浏览器都完全支持它
如果浏览器兼容性不是您的主要关注点* ,您可以尝试访问KeyboardEvent
的.repeat
属性,如下所述:
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat
通过在你的处理函数中做这样的事情:
function keyDown (e) {
if (e.repeat) { return }
// do stuff here
}
您可以避免重复击键。
*:在MDN站点上说它可以在Firefox中运行,我在Chrome中成功使用了它,所以两大浏览器应该没有问题
var fired = false;
element.onkeydown = function() {
if(!fired) {
fired = true;
// do something
}
};
然后使用 onkeyup 事件
element.onkeyup = function() {
fired = false;
};
尝试这个 :)
您可以通过简单地确定keydown
是否为真来确定脚本中的任何其他地方是否按下了键! 您还可以通过替换console.log();
在某个键关闭时执行其他脚本console.log();
当一个键被关闭时,无论你想关闭什么。
请告诉我这是否可以改进。
var keydown = false; window.addEventListener('keydown', function() { if (!keydown) { keydown = true; console.log('key down'); } window.addEventListener('keyup', function() { keydown = false; }); });
处理此问题的另一种方法(由我的朋友建议):
请注意每次 keydown 事件发生时的时间戳
计算当前时间戳(t2)和前一个时间戳(t1)之间的差异
(a) 如果差异小于某个预先确定的阈值,那么它是第二次 keydown(意味着我们已经执行了在该事件上发生的代码)。 因此,我们可能会选择不再执行代码
(b) 如果差值大于预定阈值,则为第一个 keydown。 因此,我们将执行代码
上面的解决方案不考虑多次按键(想象一个游戏,用户可以同时按下向上和向左,但都只需要触发一次)。 我需要一个通用解决方案来禁用所有键的多个 keyPress 上的重复键:
// create an array with 222 (number of keycodes) values set to true
var keyEnabledArray = Array(222).fill(true);
document.onkeydown = function(e){
// disable the key until key release
if(keyEnabledArray[e.keyCode]) {
keyEnabledArray[e.keyCode] = false;
}
};
document.onkeyup = function(e){
// enable the specific key on keyup
keyEnabledArray[e.keyCode] = true;
};
检查下面的片段:
// create an array with 222 true values var keyEnabledArray = Array(222).fill(true); document.onkeydown = function(e){ // disable the key until key release if(keyEnabledArray[e.keyCode]) { keyEnabledArray[e.keyCode] = false; document.getElementById('console').innerHTML += e.keyCode + '<br>'; } }; document.onkeyup = function(e){ keyEnabledArray[e.keyCode] = true; };
Press a key: <div id='console'></div>
为避免重复keydown
事件,请在触发后阻止它并使用keyup
解除阻止。 你应该避免变量“fired”是全局的,所以在旧版本的 JS 中使用带有 ES6+ 的代码块或闭包。
对于 ES6:
{ let fired = false; // code block to exclude 'fired' from global scope
element.addEventListener('keydown', (e) => {
// only accept key down when was released
if(!fired) {
fired = true;
// check what key pressed...
if (e.keyCode === 32) {
// and do what you need with it
}
}
});
element.addEventListener('keyup', (e) => {
fired = false;
});
}
对于旧版本的 JS 使用 IIFE:
(function(){
let fired = false;
element.addEventListener('keydown', function(e) {
// only accept key down when was released
if(!fired) {
fired = true;
// check what key pressed...
if (e.keyCode === 32) {
// and do what you need with it
}
}
});
element.addEventListener('keyup', function(e) {
fired = false;
});
})();
使用keyup
事件。 当他们的钥匙被解除时它被触发。
与上面来自匈牙利的解决方案不同,如果e.repeat
为 true,则return false
,我的用例要求我执行以下操作以有效禁用文本输入/文本区域上的 onChange 事件。
function keyDown (e) {
if(e.repeat) {
e.preventDefault()
}
// do stuff here
}
我的用例的更大上下文(在 JSX 中):
<textarea
ref={formulaInput}
defaultValue={formulaDefinition.string}
onDoubleClick={handleLock}
onKeyUp={handleUnlock}
onKeyDown={(e) => {
if(e.repeat) {
e.preventDefault()
}
}}
onKeyPress={(e) => {
if(e.repeat) {
e.preventDefault()
}
}}
readOnly={!focusLock}
onChange={handleChange}
className={`formula-input ${focusLock ? 'formula-input__locked' : ''}`}
id='2'
></textarea>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.