KeyboardEvent: code 属性

可用性有限

此特性不是基线特性,因为它在一些最广泛使用的浏览器中不起作用。

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

如果输入设备不是物理键盘,而是虚拟键盘或辅助功能设备,则浏览器会尽量使返回的值与物理键盘的操作相匹配,以最大程度地提高物理和虚拟输入设备之间的兼容性。

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

例如,在 QWERTY 布局键盘上,Q 键返回的 code"KeyQ",但相同 code 值在 Dvorak 键盘上代表 ' 键,在 AZERTY 键盘上代表 A 键。这使得无法使用 code 的值来确定用户按键的名称,除非他们使用的是预期的键盘布局。

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

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

示例

实践 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: "Helvetica", "Arial", 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);
});

动手试试

为确保按键能够发送到示例,请在按下按键之前单击或聚焦下面的输出框。

在游戏中处理键盘事件

此示例为 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 transform 来处理应用旋转和位置。

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

动手试试

为确保按键能够发送到示例代码,请在按下按键之前单击或聚焦下面的黑色游戏区域。

此代码有几种可以改进的地方。大多数真正的游戏会监听 keydown 事件,在发生时开始移动,并在相应 keyup 事件发生时停止移动,而不是依赖按键重复。这将允许更平滑、更快的移动,但也能让玩家同时进行移动和转向。还可以使用过渡或动画使飞船的移动更平滑。

规范

规范
UI 事件
# dom-keyboardevent-code

浏览器兼容性