KeyboardEvent: code プロパティ
=========================

`KeyboardEvent.code` プロパティは、（キー入力によって入力された文字ではなく）キーボード上の物理的なキーを表します。つまり、このプロパティはキーボードレイアウトや修飾キーの状態によって変更される前の値を返します。

入力機器が物理キーボードではなく、仮想キーボードやアクセシビリティ機器である場合、返値は物理キーボードから入力された場合にできるだけ近づくよう、物理キーボードと仮想入力機器との互換性を最大にするよう、ブラウザーによって設定されます。

このプロパティは、キーに関連付けられている文字ではなく、入力機器上の物理的な位置に基づいてキー入力を扱いたいときに役立ちます。これは特に、キーボードをゲームパッドのように使いたい場合などに有用です。ただし、 `KeyboardEvent.code` で報告された値を用いてキー入力で生成される文字を判断するべきではありません。キーコード名がキー上に印刷されている実際の文字や、キーが押されたときにコンピューターが生成する文字と一致するとは限らないからです。

例えば、返ってきた `code` が "`KeyQ`" は QWERTY レイアウトのキーボードでは `Q` キーですが、同じ Dvorak キーボードでは同じ `code` の値が `'` キーを表し、 AZERTY キーボードでは `A` キーを表すものでもあります。したがって、すべてのユーザーが特定のキーボードレイアウトを使用しているわけではないため、 `code` の値を用いてユーザーが認識しているキーの名前が何であるかを特定することはできません。

キーイベントに対応する文字が何であるかを判別するには、代わりに `KeyboardEvent.key` プロパティを使用してください。

値
-

Windows, Linux, macOS におけるコード値は、 KeyboardEvent: コード値のページにあります。

例
-

### KeyboardEvent の使用例

#### HTML


```html
<p>
  キーボードのキーを押して、 KeyboardEvent のキーとコードの値がそれぞれどうなっているかを確認しましょう。
</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,
);
```


#### 試してみましょう

キー入力をサンプルコードに取得させるために、キーを入力する前に output ボックスをクリックしてください。

### ゲームでのキーボードイベントの扱い

この例では、典型的な "WASD" キーボードレイアウトを使用して前進、左折、後退、右折するゲームのキーボード入力を処理する `keydown` イベントに対するイベントリスナーを確立しています。これは、ユーザーが AZERTY キーボードを使用している場合など、実際に対応する文字が何であるかに関係なく、物理的に同じ 4 つのキーを使用します。

#### HTML


```html
<p>
  WASD キー（AZERTY キーボードでは
  ZQSD）を使って移動したり方向を変えたりしましょう。
</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();
    }
  },
  true,
);
```


#### 試してみましょう

キー入力が確実にサンプルコードに反映されるように、キーを押す前に下の黒いゲームプレイフィールドをクリックまたはフォーカスしてください。

このコードを改善する方法はいくつかあります。実際のゲームでは、キーリピートに頼るのではなく、`keydown` イベントを監視して、それが発生したら動作を開始し、対応する `keyup` が発生したら動作を停止することがほとんどだと思います。そうすることで、よりスムーズで高速な移動が可能になり、プレイヤーは移動と操舵を同時に行えるようになります。トランジションやアニメーションを使用して、自機の動きをより滑らかにすることもできます。

仕様書
---

| Specification |
| --- |
| UI Events # dom-keyboardevent-code |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.