javascript - 用另一个键按下时发生两次按键事件

标签 javascript jquery keyevent key-events

在我的游戏中,我使用事件监听器 keyupkeydown 来跟踪按下了哪些键(this.input 是对下面的Input函数):

$(document.body).on('keydown', this.input.keyPress.bind(this.input));
$(document.body).on('keyup', this.input.keyPress.bind(this.input));

一切都按预期进行,直到我同时按下 2 个键。左键使玩家向左移动,Shift键发射武器。单独来看,它们工作得很好。但是,如果同时按下并按住两者,则玩家会射击两次。

这是我用来处理输入的代码(为了简洁删除了其他关键事件)

shootSpecial 只应调用一次,因为 keyMap.shiftkeydown 上仅为 true。一旦触发 keyup,它就会被设置为 false: keyMap[key] = e.type === 'keydown';

var Input = function () {
  var keyMap = {};

  this.handleKeyPress = function () {
    if (keyMap.arrowleft === true) {
      game.player.moving.left = true;
    } else if (keyMap.shift === true) {
      game.player.shootSpecial();
    }
  };

  this.keyPress = function (e) {
    var key = e.key.toLowerCase();
    if (key === ' ') {
      key = 'space';
    }
    keyMap[key] = e.type === 'keydown';
    console.log(key, keyMap[key]);
    this.handleKeyPress();
  };
};

console.log 报告 leftshiftkeydown 上为 true > 然后在 keyup 上都是 false,所以我不太确定为什么它会触发 shootSpecial 事件两次。

var keyMap = {};
var handleKeyPress = function () {
  if (keyMap.arrowleft === true) {
    console.log('left');
  } else if (keyMap.shift === true) {
    console.log('shift');  
  }
};

var keyPress = function (e) {
  var key = e.key.toLowerCase();
  keyMap[key] = e.type === 'keydown';
  if (document.getElementById(key))
    document.getElementById(key).innerText = e.type === 'keydown';
  
  handleKeyPress();
}

document.addEventListener('keydown', keyPress);
document.addEventListener('keyup', keyPress);
LEFT:<div id="arrowleft">false</div>
SHIFT:<div id="shift">false</div>

正如您通过 fiddle 所看到的,一个事件被调用两次。

最佳答案

您的问题是您使用相同的代码处理 keydown 和 keyup,结果是在按下 key2 的同时释放 key1 与按下 key2 具有相同的效果。

修复方法非常简单:根本不要在 keyup 事件上调用您的 handleKeyPress 函数。

var keyMap = {};
var handleKeyPress = function () {
  if (keyMap.arrowleft === true) {
    console.log('left');
  } else if (keyMap.shift === true) {
    console.log('shift');  
  }
};

var keyPress = function (e) {
  var key = e.key.toLowerCase();
  keyMap[key] = e.type === 'keydown';
  if (document.getElementById(key))
    document.getElementById(key).innerText = e.type === 'keydown';
  
  // Only call handleKeyPress if the key is pressed
  if (keyMap[key]) {
    handleKeyPress();
  }
}

document.addEventListener('keydown', keyPress);
document.addEventListener('keyup', keyPress);
LEFT:<div id="arrowleft">false</div>
SHIFT:<div id="shift">false</div>

<小时/>

添加建议以回应 OP 的评论。你的问题是你的handleKeyPress()没有关于该键是被按下还是被按下的信息,它也不知道哪个键被按下,只知道在调用它时哪些键被按下。为了实现你的目标,我会做这样的事情:

var keyPress = function (e) {
  var key = e.key.toLowerCase(),
      isKeyDown = e.type === "keydown",
      output = key + (isKeyDown ? "-down" : "-up") + ": ";
  
  switch (key) {
    case "shift":
      if (isKeyDown) {
        output += "pew pew";
      } else {
        output += "doing nothing"
      }
      break;
      
    case "arrowleft":
      output += "updating walking_left";
      document.getElementById("walking_left").innerText = isKeyDown;
      break;
      
    default:
      output += "doing nothing";
  }

  console.log(output);
};

document.addEventListener('keydown', keyPress);
document.addEventListener('keyup', keyPress);
Walking left:<div id="walking_left">false</div>

关于javascript - 用另一个键按下时发生两次按键事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39923228/

相关文章:

java - 从 Java 中的单独进程捕获击键

javascript - 按组和标题对数组进行排序

javascript - 主干内存泄漏: always do remove() before render()

asp.net-mvc - JQUERY ajax 将空值从 MVC View 传递到 Controller

jquery,修改插件的选项

java - Java 中的关键事件 - 初学者帮助

javascript - 如何防止光标回车?

javascript - 请求 Javascript/Angular 遇到异步问题

jquery - 如何为 jQuery on() 方法编写 Jasmine 测试用例

java - 如何从另一个类(class)获取 Keyevent?