首页 > 解决方案 > 使用带有多个键的 onkeydown 时出现“故障”

问题描述

按住单个箭头键时,该功能正常工作。

但是,当我然后按住第二个箭头键并释放第二个键时,就会出现问题,不再检测到第一个按住的键。

我的功能的简化版本如下:

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重复一遍,因为我仍然拿着向上箭头。然而,它不会这样做。

为什么会这样?我应该怎么做才能解决这个问题,以便我的箭头键仍然被检测为被按住?

标签: javascriptonkeydown

解决方案


为每个箭头键初始化一个间隔计时器,当它们被按下时运行。

释放每个箭头后,清除它们的间隔计时器:

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


推荐阅读