将onkeydown与多个键一起使用时出现“毛刺”

时间:2019-06-13 21:27:25

标签: javascript onkeydown

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

但是,当我然后按住第二个箭头键并释放第二个键时,将不再检测到该问题,从而出现问题。

我的函数的简化版本如下:

variable "subnets" {
    default = [
        {
            name = "subnet-01"
            id = 1
        },
        {
            name = "subnet-02"
            id = 2
        }
    ]
}

output "subnet-one" {
    value = [
        for subnet in var.subnets:
            subnet.id if subnet.name == "subnet-01"
    ][0]
}

因此,如果我按住UP向上箭头键,则在我按住该键时反复说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

我的期望是,由于我仍然按住UP箭头,因此它会继续反复重复说39 is UP。但是不会这样做。

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

3 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

您的箭头键 仍被检测为按下:其keydown事件已触发,而其keyup事件未触发。 keyupkeydown仅在发生更改时才会触发,唯一的例外是:操作系统生成的键盘重复事件。 (您可以通过选中e.repeat将其过滤掉。)

如果您想要一种简单的方法来查看当前被拒绝的内容,则必须自己维护该列表:

const keysHeld = {};

document.body.addEventListener('keydown', evt => {
  keysHeld[evt.keyCode] = true;
});
document.body.addEventListener('keyup', evt => {
  keysHeld[evt.keyCode] = false;
});

(请注意,keyCode已过时,应尽可能使用code。)

答案 2 :(得分:0)

您可以通过使用数组跟踪按下的键并使用计时器来监视数组来解决此问题。

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