KeyboardEvent: code 属性

KeyboardEvent.code 属性表示键盘上的物理按键(而不是按下按键生成的字符)。换句话说,此属性返回一个不受键盘布局或修饰键状态影响的值。

如果输入设备不是物理键盘,而是虚拟键盘或辅助功能设备,则浏览器将返回的值设置为尽可能与物理键盘上的情况相匹配,以最大限度地提高物理和虚拟输入设备之间的兼容性。

当您希望根据输入设备上的物理位置而不是与这些按键关联的字符来处理按键时,此属性很有用;这在编写处理模拟使用键盘上的按键的游戏手柄式环境的输入的代码时尤其常见。但是请注意,您无法使用 KeyboardEvent.code 报告的值来确定按键生成的字符,因为按键码的名称可能与按键上打印的实际字符或按键按下时计算机生成的字符不匹配。

例如,对于 QWERTY 布局键盘上的 Q 键,返回的 code 为“KeyQ”,但相同的 code 值也表示 Dvorak 键盘上的 ' 键和 AZERTY 键盘上的 A 键。这使得如果用户没有使用预期的键盘布局,则无法使用 code 的值来确定按键的名称。

要确定与按键事件对应的字符,请改用 KeyboardEvent.key 属性。

Windows、Linux 和 macOS 的代码值列在 KeyboardEvent: 代码值 页面上。

示例

练习 KeyboardEvent

HTML

html
<p>
  Press keys on the keyboard to see what the KeyboardEvent's key and code values
  are for each one.
</p>
<div id="output" tabindex="0"></div>

CSS

css
#output {
  font-family: Arial, Helvetica, sans-serif;
  border: 1px solid black;
  width: 95%;
  margin: auto;
}
#output:focus-visible {
  outline: 3px solid dodgerblue;
}

JavaScript

js
window.addEventListener(
  "keydown",
  (event) => {
    const p = document.createElement("p");
    p.textContent = `KeyboardEvent: key='${event.key}' | code='${event.code}'`;
    document.getElementById("output").appendChild(p);
    window.scrollTo(0, document.body.scrollHeight);
  },
  true,
);

试试看

要确保按键进入示例,请在按下按键之前单击或聚焦下面的输出框。

在游戏中处理键盘事件

此示例为 keydown 事件建立了一个事件侦听器,该侦听器处理使用典型“WASD”键盘布局进行向前、向左、向后和向右转向的游戏的键盘输入。无论实际对应的字符是什么,这都将物理使用相同的四个按键,例如用户是否使用 AZERTY 键盘。

HTML

html
<p>Use the WASD (ZQSD on AZERTY) keys to move and steer.</p>
<svg
  xmlns="http://www.w3.org/2000/svg"
  version="1.1"
  class="world"
  tabindex="0">
  <polygon id="spaceship" points="15,0 0,30 30,30" />
</svg>

CSS

css
.world {
  margin: 0px;
  padding: 0px;
  background-color: black;
  width: 400px;
  height: 400px;
}
.world:focus-visible {
  outline: 5px solid dodgerblue;
}
#spaceship {
  fill: orange;
  stroke: red;
  stroke-width: 2px;
}

JavaScript

JavaScript 代码的第一部分建立了一些我们将要使用的变量。shipSize 包含玩家移动的飞船的大小,为了方便起见。position 用于跟踪飞船在游戏场中的位置。moveRate 是每个按键移动飞船向前和向后的像素数,而 turnRate 是左右转向控件每次按键应用的旋转度数。angle 是应用于飞船的当前旋转量(以度为单位);它从 0°(向上直指)开始。最后,spaceship 设置为引用 ID 为 "spaceship" 的元素,该元素是表示玩家控制的飞船的 SVG 多边形。

js
let shipSize = {
  width: 30,
  height: 30,
};

let position = {
  x: 200,
  y: 200,
};

let moveRate = 9;
let turnRate = 5;

let angle = 0;

let spaceship = document.getElementById("spaceship");

接下来是函数 updatePosition()。此函数将飞船要移动的距离作为输入,其中正数表示向前移动,负数表示向后移动。此函数根据移动距离和飞船当前朝向计算飞船的新位置。它还处理确保飞船跨越游戏场的边界而不是消失。

js
function updatePosition(offset) {
  let rad = angle * (Math.PI / 180);
  position.x += Math.sin(rad) * offset;
  position.y -= Math.cos(rad) * offset;

  if (position.x < 0) {
    position.x = 399;
  } else if (position.x > 399) {
    position.x = 0;
  }

  if (position.y < 0) {
    position.y = 399;
  } else if (position.y > 399) {
    position.y = 0;
  }
}

refresh() 函数通过使用 SVG 变换 处理应用旋转和位置。

js
function refresh() {
  let x = position.x - shipSize.width / 2;
  let y = position.y - shipSize.height / 2;
  let transform = `translate(${x} ${y}) rotate(${angle} 15 15) `;

  spaceship.setAttribute("transform", transform);
}
refresh();

最后,addEventListener() 方法用于开始侦听 keydown 事件,通过更新飞船位置和旋转角度对每个按键进行操作,然后调用 refresh() 以在其新位置和角度绘制飞船。

js
window.addEventListener(
  "keydown",
  (event) => {
    if (event.defaultPrevented) {
      return; // Do nothing if event already handled
    }

    switch (event.code) {
      case "KeyS":
      case "ArrowDown":
        // Handle "back"
        updatePosition(-moveRate);
        break;
      case "KeyW":
      case "ArrowUp":
        // Handle "forward"
        updatePosition(moveRate);
        break;
      case "KeyA":
      case "ArrowLeft":
        // Handle "turn left"
        angle -= turnRate;
        break;
      case "KeyD":
      case "ArrowRight":
        // Handle "turn right"
        angle += turnRate;
        break;
    }

    refresh();

    if (event.code !== "Tab") {
      // Consume the event so it doesn't get handled twice,
      // as long as the user isn't trying to move focus away
      event.preventDefault();
    }
  },
  true,
);

试试看

要确保按键进入示例代码,请在按下按键之前单击或聚焦下面的黑色游戏场地。

此代码可以改进的地方有很多。大多数真实的游戏会监视 keydown 事件,在发生这种情况时启动运动,并在相应的 keyup 发生时停止运动,而不是依赖于按键重复。这将允许更平滑和更快的移动,但也允许玩家同时移动和转向。也可以使用过渡或动画使飞船的移动更平滑。

规范

规范
UI 事件
# dom-keyboardevent-code

浏览器兼容性

BCD 表仅在浏览器中加载