当按住单个箭头键时,函数可以正常工作。
但是,当我按住第二个箭头键并释放第二个键时,就会出现问题,因为第一个键不再被检测到。
我的函数的简化版本如下:
document.body.onkeyup = function(e){
if ([37,38,39,40].indexOf(e.keyCode) > -1){
var key_pressed = e.keyCode || e.which;
console.log(key_pressed + " is UP")
}
if([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
e.preventDefault();
}
};
document.body.onkeydown = function(e){
if ([37,38,39,40].indexOf(e.keyCode) > -1){
var key_pressed = e.keyCode || e.which;
console.log(key_pressed + " is DOWN")
}
if([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
e.preventDefault();
}
};
因此,如果我按住向上箭头键,它会在我按住键时反复显示38 is DOWN
。
然后,如果我按向右箭头键,当我按住两个键时,它会反复显示39 is DOWN
。
然后,如果我松开右箭头键,它会显示39 is UP
.
我的期望是让它继续重复说38 is DOWN
,因为我仍然持有向上箭头。但是,它不会这样做。
为什么会这样?我应该怎么做才能解决这个问题,以便我的箭头键仍然被检测到被按住?
为每个箭头键初始化一个间隔计时器,该计时器在按下箭头键时运行。
释放每个箭头后清除它们的间隔计时器:
var timer = [];
document.body.onkeyup = function(e){
let key = e.keyCode || e.which;
if ([37,38,39,40].includes(key)) {
console.log(key + " is UP");
clearTimeout(timer[key]); // stop this key's timer
timer[key] = null; // clear it so it can be initialized again
}
if ([32, 37, 38, 39, 40].includes(e.keyCode)) {
e.preventDefault();
}
};
document.body.onkeydown = function(e) {
let key = e.keyCode || e.which;
if ([37,38,39,40].includes(key) && !timer[key]) {
clearTimeout(timer[key]);
timer[key] = setInterval(() => { // create a timer for this key
console.log(key + " is DOWN")
}, 100);
}
if ([32, 37, 38, 39, 40].includes(key)) {
e.preventDefault();
}
};
您的箭头键仍被检测为按住:其keydown
事件已触发,而其keyup
事件尚未触发。 keyup
和keydown
仅在发生更改时才触发,但有一个例外:操作系统生成的键盘重复事件。(您可以通过选中e.repeat
来过滤掉这些内容。
如果你想要一种简单的方法来查看当前被压制的内容,你必须自己维护该列表:
const keysHeld = {};
document.body.addEventListener('keydown', evt => {
keysHeld[evt.keyCode] = true;
});
document.body.addEventListener('keyup', evt => {
keysHeld[evt.keyCode] = false;
});
(请注意,keyCode
已弃用,如果可能,应使用code
。
您可以通过使用数组跟踪按下的键并使用计时器监视数组来解决此问题。
var keysDown = new Array();
document.body.onkeyup = function(e) {
if ([37, 38, 39, 40].indexOf(e.keyCode) > -1) {
var key_pressed = e.keyCode || e.which;
for (var a = 0; a < keysDown.length; a++) {
if (keysDown[a] == key_pressed) {
keysDown.splice(a, 1);
}
}
}
};
function update() {
var message = "";
for (var a = 0; a < keysDown.length; a++) {
message += keysDown[a] + " is down ";
}
if (message != "") {
console.log(message);
}
}
var interval = setInterval(update, 20);
document.body.onkeydown = function(e) {
if ([37, 38, 39, 40].indexOf(e.keyCode) > -1) {
var key_pressed = e.keyCode || e.which;
var found = false;
for (var a = 0; a < keysDown.length; a++) {
if (keysDown[a] == key_pressed) {
found = true;
}
}
if (!found) {
keysDown.push(key_pressed)
}
}
};