WAI-ARIAの基本 - ウェブ開発を学ぶ

WAI-ARIAの基本
===========

* 前のページ
* Overview: Accessibility
* 次のページ

前回の記事に続いて言えることですが、意味論的ではない HTML や JavaScript によって更新される動的なコンテンツを含むような、複雑な UI コントロールの作成は難しくなることがあります。 WAI-ARIA は、ブラウザーや支援技術が認識できるさらなる意味論を追加することによってそのような問題に対処し、ユーザーの理解を助ける技術です。 ここでは、アクセシビリティを向上させるための基本的な使い方を説明します。

|  |  |
| --- | --- |
| 前提知識: |
 基本的なコンピューターの知識、HTML、CSS、JavaScript に対する基本的な理解、
 前回までの記事に対する理解。
  |
| 目標: | WAI-ARIA、および、アクセシビリティを向上させるために必要に応じて有用な追加の意味論を提供する方法について知識を得ること。 |

WAI-ARIA って何？
-------------

まずは、WAI-ARIA とは何か、そして何ができるのかという点から始めましょう。

### 全く新しい問題

ウェブアプリがより複雑で動的なものになると、新しいアクセシビリティの機能と問題が明らかになってきます。

例えば、 HTML は普遍的なページの機能を定義するためにいくつもの意味論的要素を取り入れました（`<nav>`、`<footer>` 等）。 これらが利用可能になる以前は、開発者は `<div class="nav">` のように単に `<div>` を ID や class と共に使っていましたが、メインナビゲーションのようなページ内の機能をプログラムで識別する簡単な方法が無いために問題がありました。

初期の解決方法は、ナビゲーションへとリンクさせるため、次のようにページ上部に 1 つ以上の隠しリンク（もしくは他の何か）を追加することでした。

```html
<a href="#hidden" class="hidden">Skip to navigation</a>
```

しかしこれは簡潔な方法ではない上に、スクリーンリーダーがページの先頭から読み込む場合にのみ利用できるものでした。

他の例としては、アプリが日付選択のための日付ピッカーや値選択のためのスライダーなどの複雑なコントロールを使いだしたケースがあります。 HTML は、そのようなコントロールを表す特別な入力タイプを提供しています。

```html
<input type="date" /> <input type="range" />
```

これらはブラウザー間で十分にサポートされておらず、またスタイル付けすることが非常に困難であるため、ウェブサイトのデザインに合わせる上で不便となります。 結果として、開発者は多くの場合 JavaScript ライブラリーを利用して複数のネストされた `<div>` でそのようなコントロールを生成したり、クラス名を持った表要素に対して CSS によるスタイル付けと JavaScript による制御を行ったりします。

この場合の問題は、見た目上は動作するものの、スクリーンリーダーはそれらが何なのか全く理解できず、ユーザーには意味を成さないごちゃごちゃの要素であるとしか教えられないという点にあります。

### WAI-ARIA の導入

WAI-ARIA は W3C によって定められた仕様で、要素に適用できる追加の意味論を提供する一連の HTML 属性を定義しており、それが欠けているどのような場所でもアクセシビリティを向上させます。 この仕様では、主に次の 3 つの機能があります。

* **ロール (Role)** — これは要素が何か、もしくは何をするかを定義します。 多くの場合はいわゆるランドマークロール (landmark role) であり、主に HTML 構造要素の意味づけを複製します。 例えば、 `role="navigation"` (`<nav>`) や `role="complementary"` (`<aside>`) などです。 しかし、それ以外にも別のページ構造を定義するロールもあります。 例えば、 `role="banner"` 、 `role="search"` 、 `role="tablist"` 、 `role="tabpanel"` 等で、 UI に多く見られます。
* **プロパティ (Property)** — これは要素の性質を定義するものであり、追加の意図や意味論を与えるために使用することができます。 例えば、 `aria-required="true"` はフォーム入力が有効となるために値を入力しなければならないことを定義し、 `aria-labelledby="label"` は、要素に ID を追加することで、複数の場合も含めてページ内の他のどの要素からもラベルとして参照することを可能にします。 これは `<label for="input">` ではできません。 別の例として、 `aria-labelledby` を使って主な説明を含む 1 つの `<div>` が表の複数セルのラベルであると指定することができますし、画像の代替テキストの代わりとして使用することもできます。 これは、 `alt` 属性で繰り返すのではなく、ページの既存の情報を画像の代替テキストとして指定します。 代替テキスト で例を確認することができます。
* **ステート (State)** — 要素の現在の状態を定義する特別なプロパティです。 例えば、 `aria-disabled="true"` は、フォーム入力が現在 disabled であることをスクリーンリーダーに対して伝えます。 ステートはプロパティとは異なり、プロパティはアプリのライフサイクルを通して変化しないのに対して、ステートは主に JavaScript によって変更されます。

WAI-ARIA 属性の重要な点は、ブラウザーのアクセシビリティ API（スクリーンリーダーはここから情報を取得する）によって提供される情報を除いて、それらはウェブページに何の影響も与えないという点です。 WAI-ARIA はウェブページの構造や DOM に影響を与えませんが、 CSS の要素選択で利用することが可能です。

**メモ:** ARIA ロールの使用方法と追加情報へのリンクを含む便利なリストを確認することができます。WAI-ARIA の仕様書ではロールの定義（英語）を、このサイトでは ARIA ロールを参照してください。

この仕様では、プロパティとステートの追加情報を含んだリストも確認することができます。 ステートとプロパティの定義（すべての aria-\* 属性）（英語）を見てください。

### WAI-ARIA はどこで対応されているか

この質問に答えるのは簡単ではありません。 次の理由より、どこで、WAI-ARIA のどの機能が対応されているのかを記述する決定的なリソースを見つけることが難しいためです。

1. WAI-ARIA には大量の機能がある。
2. 検討しなければいけないオペレーティングシステム、ブラウザー、スクリーンリーダーの組み合わせが大量にある。

最後の点は重要です。 そもそもスクリーンリーダーを使用するためには、オペレーティングシステムが所定のアクセシビリティ API を持つブラウザーを動作させる必要があり、それはスクリーンリーダーが動作するために必要となる情報を提供しなければいけません。 ほとんどの人気の OS は、スクリーンリーダーが動作可能である 1 つか 2 つの所定のブラウザーを持っています。 Paciello Group は、この件に関してほぼ最新のデータを投稿しています — ラフガイド: ブラウザー、オペレーティングシステム、スクリーンリーダーのサポート（英語）を見てください。

次に、ブラウザーが問題となっている ARIA の機能に対応しているのか、および API を通してそれらを公開しているのかという点を気にする必要があります。 しかし、スクリーンリーダーがそれらの情報を認識し、ユーザーに有益なやり方で伝えているのかという点もまた気にしなければいけません。

1. ブラウザーはほぼすべてが対応しています。
2. スクリーンリーダーの ARIA の対応状況はそこまでではありませんが、多くの一般的なスクリーンリーダーはそれに近いものになってきています。 Powermapper による WAI-ARIA のスクリーンリーダーの互換性（英語）の記事で、サポート状況を確認することができます。

この記事では、全ての WAI-ARIA の機能と詳細についてカバーするわけではありません。 代わりに、あなたが知るべき最も重要な WAI-ARIA の機能についてカバーします。 もしサポートの詳細について何も記述してしない場合は、その機能が十分にサポートされていると想定してください。 この例外がある場合は、明確に記述します。

**メモ:** JavaScript ライブラリには WAI-ARIA をサポートしているものがありますが、それはライブラリが複雑なフォームコントロールのような UI を生成した場合に、アクセシビリティを向上させるための ARIA 属性を追加することを意味します。 迅速な UI 開発のためにサードパーティーの JavaScript ライブラリを探しているのであれば、その決断を下す際、UI のアクセシビリティのサポートを重要な要素として必ず考慮すべきです。 良い例としては、 jQuery UI（jQuery UI について: ディープアクセシビリティサポート（英語）を見てください）、 ExtJS 、 Dojo/Dijit があります。

### いつ WAI-ARIA を使うべき？

私達は WAI-ARIA が作られるに至ったいくつかの問題について最初の方で話しましたが、基本的には WAI-ARIA が有用となる 4 つの主な場面があります。

1. **道しるべ/ランドマーク (Signpost/Landmark)**: ARIA の `role` 属性の値は、HTML 要素の意味論（例えば `<nav>`）を再現するランドマークとして振る舞ったり、 `search`、`tablist`、`tab`、`listbox` のように HTML の意味論の範囲外となる道しるべ (signpost) を異なる機能エリアに提供することができます。
2. **動的なコンテンツの更新**: スクリーンリーダーは、絶えず更新されるコンテンツが得意ではない傾向があります。例えば、ARIA の `aria-live` を使うことで、 XMLHttpRequest や DOM API を通してコンテンツが更新された場合に、スクリーンリーダーのユーザーに対してそれを伝えることができます。
3. **キーボードのアクセシビリティの向上**: キーボードのアクセシビリティを最初から持つ HTML 要素がありますが、 JavaScript を使ってそれ以外の要素に同じようなインタラクションをさせる場合、スクリーンリーダーにとって困難が生じます。 こうしなければならない場合、 WAI-ARIA は他の要素に対してフォーカスを得る手段を提供しています（`tabindex` の使用）。
4. **意味論的ではないコントロールのアクセシビリティ**: ネストした一連の `<div>` が CSS/JavaScript と共に複雑な UI 機能を構成していたり、ネイティブのコントロールが JavaScript によって大きく強化/変更されている場合、アクセシビリティの提供は困難になります。 そこに意味論や手がかりが無ければ、スクリーンリーダーのユーザーはその機能が何をするのか判断するのが難しくなるでしょう。 このような状況では、 `button`、`listbox`、`tablist` といったロールの組み合わせ、もしくは `aria-required` や `aria-posinset` などのプロパティにより機能の手がかりを提供することで、 ARIA は足りないものを補うことができます。

一点忘れてはいけないのが、 **WAI-ARIA は必要な場合のみ使用する**という点です。 理想的には、スクリーンリーダーのユーザーの理解に必要となる意味論の提供は、常に ネイティブの HTML 機能 を使用して行うべきです。 しかし、コードの制御が限定されていたり、 HTML 要素への実装が容易ではない複雑なものを作っているなどの理由で、これが困難となるケースがあります。 そのような場合、 WAI-ARIA はアクセシビリティを向上させる上で価値のあるツールとなります。

もう一度言いますが、必要な時だけ使ってください！

**メモ:** 実際のさまざまなユーザーによってあなたのサイトをテストすることも忘れないでください — 障害のないユーザー、スクリーンリーダーを使用するユーザー、キーボードナビゲーションを使用するユーザーなどです。 どれだけうまく動作するかという点で、彼らはあなたよりもうまく観察してくれるでしょう。

実際的な WAI-ARIA の実装
-----------------

次の節では、実際の例と共に、より詳細な 4 つの領域を見てみます。 続行する前に、これから見る例をテストできるように、スクリーンリーダーのテスト環境を用意してください。

詳細はスクリーンリーダーのテストを確認してください。

### 道しるべ/ランドマーク（Signpost/Landmark）

WAI-ARIA は `role` 属性（英語）をブラウザーに追加することで、必要に応じてあなたのサイトに付加的な意味論的価値を追加することができます。 これが有用となる最初の領域は、スクリーンリーダーのユーザーが共通のページ要素を見つけることができるようになる情報の提供です。 例を見てみましょう。私達の website-no-roles の例（実際の動作）は、次の構造を持っています。

```html
<header>
  <h1>…</h1>
  <nav>
    <ul>
      …
    </ul>
    <form>
      <!-- 検索フォーム -->
    </form>
  </nav>
</header>

<main>
  <article>…</article>
  <aside>…</aside>
</main>

<footer>…</footer>
```

もしあなたが現代のブラウザーでスクリーンリーダーのテストをした場合、いくつかの有用な情報を手に入れるでしょう。 例えば、 VoiceOver は次の内容を読み上げます。

* `<header>` 要素の上 — "banner, 2 items"（見出しと `<nav>` を含んでいる）
* `<nav>` 要素の上 — "navigation 2 items"（リストとフォームを含む）
* `<main>` 要素の上 — "main 2 items"（記事（article）と余談（aside）を含む）
* `<aside>` 要素の上 — "complementary 2 items"（見出しとリストを含む）
* 検索フォーム入力の上 — "Search query, insertion at beginning of text"
* `<footer>` 要素の上 — "footer 1 item"

VoiceOver の Landmarks メニューを見ると（VoiceOver キー + U でアクセスし、矢印キーでメニューを選択する）、多くの要素が素早くアクセスできるように綺麗に並んでいることが確認できます。

![Mac の VoiceOver によるクイックアクセシビリティのためのメニュー。バナー、ナビゲーション、メイン、補完を含むランドマークヘッダーとランドマークリスト。](/ja/docs/Learn/Accessibility/WAI-ARIA_basics/landmarks-list.png)

しかし、これは改善することができます。 検索フォームはユーザーが見つけたいと考える重要なランドマークですが、ここでは Landmarks メニューの中に列挙されておらず、検索入力（`<input type="search">`）であるということ以上に目立つランドマークとしても扱われていません。

ARIA の機能を使用してこれを改善しましょう。 まず、 HTML に対していくつかの `role` 属性を追加します。 私達のオリジナルファイルをコピーするか（index.html と style.css を参照）、 website-aria-roles の例（実際の動作）へ移動すると、次の構造を確認できます。

```html
<header>
  <h1>…</h1>
  <nav role="navigation">
    <ul>
      …
    </ul>
    <form role="search">
      <!-- 検索フォーム -->
    </form>
  </nav>
</header>

<main>
  <article role="article">…</article>
  <aside role="complementary">…</aside>
</main>

<footer>…</footer>
```

この例では、ボーナス機能も提供しています — `<input>` は `aria-label` 属性が設定されていますが、これは `<label>` 要素が含まれていない場合でもスクリーンリーダーによって読み上げられる説明ラベルを設定します。 こういうケースでは、この機能はとても便利です — このような検索フォームはよくあるものであり、簡単に識別できるので、見えるラベルを設定するとデザインを台無しにしてしまうのです。

```html
<input
 type="search"
 name="q"
 placeholder="Search query"
 aria-label="Search through site content" />
```

さて、この例を VoiceOver で見た時、次の改善を確認することができます。

* ページをブラウジングした時と、 Landmarks メニューで見た時の両方において、検索フォームが分離したアイテムとして認識される。
* フォーム入力がハイライトされた時、 `aria-label` に含まれているテキストが読み上げられる。

さらに、このサイトは IE8 のような古いブラウザーを使用しているユーザーにとってもアクセス可能となる可能性が高いので、そのために ARIA ロールを含める価値もあります。 そして、もしあなたのサイトが何らかの理由により `<div>` のみで構成されているなら、必要な意味論を提供するために確実に ARIA ロールを含めるべきです。

改善された検索フォームは、 ARIA が HTML で利用できる意味づけ以上のことができることを見せてくれました。 以下の記事、特に 意味論的でないコントロールのアクセシビリティ の節で、より多くの意味論や ARIA のプロパティ/属性が持つ力を見ることができます。 まずは、 ARIA が動的コンテンツの更新をどのように助けるかを見てみましょう。

### 動的なコンテンツの更新

DOM に読み込まれたコンテンツ（本文の内容や、画像の代替テキストなど）はスクリーンリーダーを用いて容易にアクセスできます。 従って、テキストコンテンツで作られた伝統的で静的なウェブサイトを、視覚的ハンディキャップを持つ人々にとってアクセス可能にすることは容易です。

問題はモダンなウェブアプリが静的なテキストだけを使うことは少ないという点です。 それらは動的に更新されるコンテンツ、すなわち、XMLHttpRequest、Fetch、DOM API などの機構を通してページ全体をリロードすることなく更新を行うコンテンツで構成されることが多いです。 このような箇所はしばしば\*\*ライブリージョン（live region）\*\*と呼ばれます。

簡単な例を見てみましょう。 aria-no-live.html をご覧ください（もしくは 動作版をご覧ください）。 この例では、ランダムに引用文を表示する 1 つの箱があります。

```html
<section>
  <h1>Random quote</h1>
  <blockquote>
    <p></p>
  </blockquote>
</section>
```

JavaScript が `XMLHttpRequest` を通して JSON ファイルを読み込みます。 この JSON ファイルには、複数のランダムな引用文とその著者が含まれています。 読み込みの完了後に `setInterval()` ループを開始し、引用文の表示を 10 秒ごとに新しいものに切り替えます。

```js
const intervalID = setInterval(showQuote, 10000);
```

これは正しく動作しますが、アクセシビリティとしてはよくありません。 コンテンツの更新がスクリーンリーダーに検知されないため、ユーザーは何が起こっているかを知ることができないからです。 これはつまらない例ですが、更新され続けるコンテンツを多く含む複雑な UI をあなたが作ることを想像してください（チャットルームや戦略ゲームの UI、動的に更新されるショッピングカートの表示など）。 ユーザーに更新を知らせる何かしらの手段がない限り、それがどんなに実用的なアプリであっても使いこなすことはできないでしょう。

幸いなことに WAI-ARIA はそのような通知を行う便利な機構を提供しています。 それが `aria-live` プロパティです。 このプロパティを要素に適用すると、スクリーンリーダーが更新されたコンテンツを読み上げてくれるようになります。 どのような緊急性をもってコンテンツを読み上げてくれるかは、次のように属性値によって変わります。

* `off:` 既定値。更新は通知されない (should not)。
* `polite`: 更新はユーザが暇になったときのみ通知される (should)。
* `assertive`: 更新は可能な限り早くユーザに通知される (should)。

aria-no-live.html と quotes.json のコピーを作成し、`<section>` タグの内容を次のように更新してください。

```html
<section aria-live="assertive">…</section>
```

これにより、コンテンツの更新があった際にスクリーンリーダーがその内容を読み上げてくれるようになります。

**メモ:** `XMLHttpRequest` を `file://` URL をもつページから呼び出そうとするとほとんどのブラウザーはセキュリティ例外を投げます。 例えば、（ダブルクリックなどにより）ファイルを直接ブラウザーで読み込んだ場合は、`file://` URL で開かれます。 動作させるためには、 ウェブサーバー（GitHub を利用するなど）やローカルウェブサーバー（Python の SimpleHTTPServer（英語）など）にファイルをアップロードする必要があります。

加えて、考慮すべきことがあります。 テキストの更新された部分だけを読み上げるべきかどうかです。 常に見出し全体を読み上げる方が、何を読み上げられているかをユーザーが認識できるという点で望ましいかもしれません。 その対象に `aria-atomic` プロパティを追加することで、このような動作を得ることができます。 手元の `<section>` の開始タグを再度更新して、次のようにしてください。

```html
<section aria-live="assertive" aria-atomic="true">…</section>
```

この `aria-atomic="true"` 属性が、更新された一部分だけではなく、要素全体のコンテンツを 1 つのまとまりとして読み上げるようスクリーンリーダーに伝えます。

**メモ:** 完成した例は aria-live.html をご覧ください（もしくは動作版をご覧ください）。

**メモ:** `aria-relevant` プロパティはライブリージョンが更新された際に何が読み上げられるかを制御するのに非常に役に立ちます。 例えば、追加や削除をされた内容だけを読み上げさせることもできます。

### キーボードでのアクセシビリティの拡張

このモジュールの他の箇所でも何度か言及したように、アクセシビリティという観点での HTML がもつ重要な能力の 1 つが、キーボードでのアクセシビリティが組み込まれていることです。 キーボードから、ボタンやフォームコントロール、リンクなどの機能にアクセスできます。 一般的に、タブキーでコントロール間を移動したり、エンター/リターンキーでコントロールの選択や活性化をしたり、必要に応じたその他の制御（例えば、上下矢印キーでの `<select>` ボックス内のオプション間の移動）ができます。

しかし、時には（ボタンや他のタイプのコントロールとして）意味論的でない要素や正しい用途ではないフォーカス可能な要素を利用するコードを書かざるをえないこともあるでしょう。 あなたが引き継いだ作りの悪いコードを修正したり、そのようなコードを必要とする複雑なウィジェットを作ったりする場合があるかもしれません。

フォーカスできないコードをフォーカス可能にするために、WAI-ARIA では `tabindex` 属性を拡張して次のようにいくつかの値を加えています。

* `tabindex="0"` — 上で示したように、この値は通常タブキーでの移動対象とならない要素をタブ移動可能にします。 この値は `tabindex` の値の中で最も便利なものです。
* `tabindex="-1"` — この値は通常タブキーでの移動対象とならない要素がプログラム的にフォーカスを受け付けられるようにします。 例えば、JavaScript を利用したりリンクのターゲットとしてフォーカスするケースです。

より詳細な議論や典型的な実装例については、HTML のアクセシビリティに関する記事 — キーボードアクセシビリティを呼び戻すように盛り込む をご覧ください。

### 意味論的でないコントロールのアクセシビリティ

この節の内容は前節の続きです。 多くの入れ子になった `<div>` 要素と CSS/JavaScript を利用して複雑な UI 機能を構築した場合、また、JavaScript で本来のコントロールの機能を拡張/改変した場合を考えてみましょう。 そのようなときには、キーボードでのアクセシビリティが損なわれるだけでなく、スクリーンリーダーのユーザーが各機能のふるまいを理解することは何らかの意味論や手がかりがない限り困難となってしまう。 そのような状況においても、ARIA はそこにあるべき意味論を補足する手助けができます。

#### フォーム検査とエラー警告

まず、CSS と JavaScript のアクセシビリティ の記事で最初に見たフォームの例を再検討しましょう（完全なまとめを再び見るには、ひかえめに保つことをお読みください）。 フォームを送信しようとした際に検査エラーがあると現れるエラーメッセージ・ボックスにいくつかの ARIA 属性を含めたことを、そのセクションの末尾で示しておきました。

```html
<div class="errors" role="alert" aria-relevant="all">
  <ul></ul>
</div>
```

* `role="alert"` は、適用先の要素を自動的にライブリージョンにします。 すると、その要素に対する変更は読み上げられます。 また、その要素が警告メッセージ（重要であり、時間 / コンテキストの影響を受ける情報）なのだ、と意味論的に特定しています。 かつ、ユーザーに警告を伝える、よりアクセシビリティに優れたより良い方法も表現しています（`alert()` の呼び出しのようなモーダルダイアログには、いくつものアクセシビリティの問題があります。 WebAIM による ポップアップウィンドウ（英語）を参照）。
* `aria-relevant` (en-US) の `all` という値は、エラーリストに対して何らかの変更がなされた際には（つまり、エラーが追加または削除された際には）エラーリストの中身を読み上げるよう、スクリーンリーダーに命令するものです。これは有用です。 なぜなら、ユーザーは、リストに何が追加され、リストから何が削除されたのかを知りたいだけでなく、何のエラーが残っているのかを知りたいでしょうから。

ARIA を使用して、更に先へ踏み込むこともできるでしょうし、なんらかの検査の手助けを更に提供することもできるでしょう。 そもそもフィールドが必須かどうかを示すことや、年齢がどの範囲にあるべきかを示すこと、などはいかがでしょうか？

1. いまの時点で、form-validation.html と validation.js のファイルのコピーをとり、それをローカル・ディレクトリーに保存してください。
2. 両ファイルをテキストエディタで開き、コードがどのように動くのかを見てください。
3. まず始めに、`<form>` 開始タグのすぐ上に次のような段落を加えるとともに、フォームの `<label>` には、両方ともアスタリスクの印をつけてください。 これは、晴眼者ユーザー用に必須フィールドに印をつける通常の方法です。

```html
<p>アスタリスク（*）が付いているフィールドは必須です。</p>
```

4. これは視覚的に意味をなしますが、スクリーンリーダーのユーザーにとっては、理解するのがそれほど容易ではありません。 さいわい、WAI-ARIA には、フォーム入力欄を埋める必要があることをユーザーに伝えるべきだとスクリーンリーダーにヒントを与えるための、`aria-required` (en-US) 属性があります。 `<input>` 要素を次のように更新してください。

```html
<input type="text" name="name" id="name" aria-required="true" />

<input type="number" name="age" id="age" aria-required="true" />
```

5. この例をここで保存してスクリーンリーダーでテストしてみれば、「Enter your name star, required, edit text（名前を入れてください　星、必須、テキストを編集）」のようなものを聞くことになるはずです。
6. 年齢の値がどうあるべきかについて、スクリーンリーダーのユーザーと晴眼者のユーザーに知らせるのも、有用かもしれません。 これはツールチップとして提示されることがよくあり、あるいは、フォームのフィールド内部のプレースホルダーとして提示されることも、多分あります。 最小値と最大値を指定するための `aria-valuemin` (en-US) プロパティと `aria-valuemax` (en-US) プロパティを、WAI-ARIA は確かに含んではいますが、これらのプロパティは、今のところそれほどちゃんとサポートされてはいないようです。 よりちゃんとサポートされている機能は、HTML の `placeholder` 属性です。 これは、何の値も入力されていないときに入力欄の中に表示されるメッセージを含むことができ、多くのスクリーンリーダーにより読み上げられます。 数値入力欄を次のように更新してください。

```html
<label for="age">Your age:</label>
<input
 type="number"
 name="age"
 id="age"
 placeholder="Enter 1 to 150"
 required
 aria-required="true" />
```

すべての入力要素に、必ず `<label>` を付けてください。スクリーンリーダーの中には、プレースホルダーテキストをアナウンスするものもありますが、ほとんどはそうではありません。フォームコントロールに `aria-label` (en-US) および `aria-labelledby` によってアクセス可能な名前を提供するという代替手段もあります。しかし、`for` 属性を持つ `<label>` 要素は、マウスユーザーを含むすべてのユーザーに対してユーザビリティを提供するため、好ましい方法です。

**メモ:** この完成した例を、form-validation-updated.html においてライブ版で見られます。

また、古典的な `<label>` 要素以上の、ある種の先進的なフォームのラベルづけ技法も、WAI-ARIA によって可能になります。 晴眼者のユーザーに対してラベルを可視にしたくない箇所にラベルを設けるために `aria-label` (en-US) プロパティを使うことについては、すでに述べました（上記の 道しるべ/ランドマーク のセクションを参照）。 別のプロパティを使う別のラベルづけ技法も、いくつかあります。 例えば、`<label>` 以外の要素をラベルとして指定したいとき、または、同じラベルで複数のフォーム入力欄にラベルづけをしたいときに `aria-labelledby` を使うとか、別の情報をフォーム入力欄に関連づけてその情報も同様に読み上げさせたいときに `aria-describedby` を使うとかいったものです。 より詳しくは、WebAIM の 高度なフォームのラベル付け（英語）の記事を参照してください。

その他にも、フォーム要素の状態を示すのに便利なプロパティやステートがたくさんあります。例えば、`aria-disabled="true"`は、フォームフィールドが無効であることを示すために使用することができます。多くのブラウザーは、無効化されたフォームフィールドをスキップしてしまうため、スクリーンリーダーで読み上げることができません。場合によっては、無効化された要素が知覚されることもあるので、無効化されたフォームコントロールが実際に無効であることをスクリーンリーダーに知らせるために、この属性を含めるのは良い考えです。

もし入力欄の無効化ステートが変化する可能性が高いなら、その変化が起きた時点と、その結果どうなったのかを示すことも、良い考えです。 例えば、form-validation-checkbox-disabled.html のデモには、チェックされると他のフォーム入力欄への更なる情報の入力を可能とするようなチェックボックスがあります。 次のように隠しライブリージョンを設定してあります。

```html
<p class="hidden-alert" aria-live="assertive"></p>
```

これは、絶対的位置指定を使って、視界からは隠してあります。 これがチェックされたり、これのチェックが外されたりすると、このチェックボックスのチェックの結果がどうなったのかをスクリーンリーダーのユーザーに伝えるために、`aria-disabled` ステートやいくつかの視覚的表示を更新するだけでなく、この隠しライブリージョン内部のテキストも更新します。

```js
function toggleMusician(bool) {
  const instruItem = formItems[formItems.length - 1];
  if (bool) {
    instruItem.input.disabled = false;
    instruItem.label.style.color = "#000";
    instruItem.input.setAttribute("aria-disabled", "false");
    hiddenAlert.textContent =
      "Instruments played field now enabled; use it to tell us what you play.";
  } else {
    instruItem.input.disabled = true;
    instruItem.label.style.color = "#999";
    instruItem.input.setAttribute("aria-disabled", "true");
    instruItem.input.removeAttribute("aria-label");
    hiddenAlert.textContent = "Instruments played field now disabled.";
  }
}
```

#### 意味論的でないボタンをボタンとして説明する

 この課程の中で既に 2、3 回、ボタンやリンクやフォーム要素に本来備わったアクセシビリティ（および、ボタンやリンクやフォーム要素の外見を模倣するために他の要素を使うことの背後に隠れた、アクセシビリティの問題）について述べました（HTML アクセシビリティの記事の UI コントロール と、上記のキーボードでのアクセシビリティの拡張を参照）。
 基本的には、多くの場合、`tabindex` とほんの少しの JavaScript を使えば、それほど問題を生じずにキーボードアクセシビリティを追加して呼び戻せます。

しかし、スクリーンリーダーについてはどうでしょうか？ スクリーンリーダーはそれでもまだ、そうした要素をボタンとは見なさないことでしょう。 もし fake-div-buttons.html の例をスクリーンリーダーで試してみれば、見せかけのボタンは「Click me!, group（クリックしてください！、グループ）」のような語句を使って報告されるでしょうし、それは明らかに混乱を招くものです。

WAI-ARIA ロールを用いてこれを修正できます。 fake-div-buttons.html のローカルコピーを作って、ボタンとしての `<div>` の各々に `role="button"` と追加してください。 例えば次のようにします。

```html
<div data-message="This is from the first button" tabindex="0" role="button">
  Click me!
</div>
```

スクリーンリーダーを使ってこれを試すと、「クリックしてください！ボタン」のようなフレーズでボタンが報告されるようになります。これはずっと良いことですが、`button` ロールのドキュメントで説明されているように、`Enter` やクリックイベントの処理など、ユーザーが期待するネイティブなボタン機能をすべて追加する必要があります。

**メモ:** とはいえ、可能な箇所では正しい意味的要素を使うことの方が常に良いのだ、ということを忘れないようにしてください。 もしボタンを作りたいなら、そして `<button>` 要素が使えるなら、`<button>` 要素を使うべきです。

#### 複雑なウィジェットを通じてユーザーを案内する

他にも、標準的な HTML で利用可能なものを超える一般的な UI 機能として、意味的でない要素構造を特定できる ロール が多数存在します。例えば `combobox` (en-US)、`slider`、`tabpanel` (en-US)、`tree` (en-US) などです。Deque 大学コードライブラリー（英語）では、このようなコントロールをどのようにアクセシブルにできるかを示す有用な例を見ることができます。

わたしたち自身の事例を検討しましょう。 単純で、絶対的位置指定をした、タブ付きのインターフェイス（CSS と JavaScript のアクセシビリティの記事の、ものごとを隠す を参照）へと戻りましょう。 これは、タブ付きの情報ボックスの例（ソースコード を参照）の中に見つかります。

この例は、このままでもキーボードアクセシビリティに関しては、うまく機能します。 幸いなことに、異なるタブ同士の間でのタブ移動が可能ですし、タブを選択して当該タブの中身を表示することもできます。 また、次の点でもかなりアクセス可能です。 すなわち、たとえ画面上で何が起きているのかが見えないとしても、コンテンツ全体にわたってスクロールすることはできますし、見出しを使って見通しを得ることもできます。 でも、そのコンテンツが何であるのかは、明らかではありません。 スクリーンリーダーは今のところ、そのコンテンツのことを、リンクのリストと、三つの見出しを備えた何らかのコンテンツである、と報告してきます。 スクリーンリーダーは、コンテンツ間にどういう関係があるのかについては、何も知らせてくれません。 コンテンツの構造に関する更なる手がかりをユーザーに与えることは、常に良いことです。

ものごとを改善するために、わたしたちは、aria-tabbed-info-box.html と呼ばれる、本例の新たなバージョンを作成しました（これがライブ版で動くところも参照）。 タブ付きのインターフェイスの構造を次のように更新しておきました。

```html
<ul role="tablist">
  <li
 class="active"
 role="tab"
 aria-selected="true"
 aria-setsize="3"
 aria-posinset="1"
 tabindex="0">
    Tab 1
  </li>
  <li
 role="tab"
 aria-selected="false"
 aria-setsize="3"
 aria-posinset="2"
 tabindex="0">
    Tab 2
  </li>
  <li
 role="tab"
 aria-selected="false"
 aria-setsize="3"
 aria-posinset="3"
 tabindex="0">
    Tab 3
  </li>
</ul>
<div class="panels">
  <article class="active-panel" role="tabpanel" aria-hidden="false">…</article>
  <article role="tabpanel" aria-hidden="true">…</article>
  <article role="tabpanel" aria-hidden="true">…</article>
</div>
```

**メモ:** ここでの最も際立った変更点は、この例にもともと存在していたリンクを削除して、単にリスト項目をタブとして使ったことです。 このようにした理由は、スクリーンリーダーのユーザーにとっての物事の紛らわしさを減らせるからであり（これらのリンクは、実際にどこかへ連れて行ってくれるものではなく、ただ見かけを変化させるだけのものなのです）、また、セット機能における setsize/position が、よりうまく機能できるようになるからです。 setsize/position がリンク上に設定されている場合、ブラウザーは、「3 分の 1」「3 分の 2」などではなく、常に「1 分の 1」と報告し続けます。

ARIA 機能は次のように使われます。

* 新たなロール、すなわち `tablist` (en-US)、`tab`、`tabpanel` (en-US) は、タブ付きインターフェイスでの重要な領域、つまり、タブ群のコンテナと、タブ自体と、対応するタブパネルを識別します。
* `aria-selected` (en-US) — 今どのタブが選択されているのかを定めます。 別のタブがユーザーにより選択されると、その別のタブ上のこの属性の値が、JavaScript を介して更新されます。
* `aria-hidden` (en-US) — スクリーンリーダーに読み上げられないように、要素を隠します。 別のタブがユーザーにより選択されると、その別のタブ上のこの属性の値が、JavaScript を介して更新されます。
* `tabindex="0"` — リンクを削除したので、リスト項目にキーボードフォーカスを与えるためには、リスト項目にこの属性を与える必要があります。
* `aria-setsize` (en-US) — 要素が一連のもののうちの一部なのだということと、その一連のものの中にいくつの項目があるのかということを、スクリーンリーダーに対して指定することが、このプロパティによって可能となります。
* `aria-posinset` (en-US) — 一連のものの中で要素がどの位置にあるのかを指定することが、このプロパティによって可能となります。 このプロパティを `aria-setsize` と一緒に用いると、現在「3 分の 1」の項目にいます、などと知らせるのに十分な情報を、スクリーンリーダーに対して提供してくれます。 多くの場合、ブラウザーは、要素の階層構造からこの情報を推測できるはずですが、`aria-posinset` は、更なる手がかりを与えるのに確実に役立ちます。

わたしたちの検査では、この新たな構造は、物事を全体的に改善するのに確かに役立ちました。 今や、タブはタブとして認識されます（例えば、スクリーンリーダーが「タブ」と話します）し、選択されたタブは、そのタブ名で読み上げられて「選択中」と示されますし、スクリーンリーダーは、どのタブ番号のところに今いるのかということも教えてくれます。 さらに、`aria-hidden` の設定（まさに隠されていないタブのみに、`aria-hidden="false"` と設定されている）のおかげで、隠されていないコンテンツのみが、ナビゲートして下ってゆける唯一のコンテンツとなっており、このことは、選択されたコンテンツを見つけやすくなったことを意味します。

**メモ:** スクリーンリーダーに読み上げさせたくないと明示的に思うものが何かある場合、スクリーンリーダーに対して、`aria-hidden="true"` 属性を与えることができます。

スキルをテストしましょう
------------

あなたはこの記事の最後までたどり着きましたが、最も重要な情報を覚えていますか？次に進む前に、この情報が記憶されているかどうかを確認するために、さらにいくつかのテストが用意されています。 Test your skills: WAI-ARIA (en-US) を参照してください。

まとめ
---

本記事は、WAI-ARIA で利用可能なすべてのものを取り扱ったとは、到底、言えません。 でも、WAI-ARIA の使い方を理解するのに十分な情報をお伝えしたはずです。 また、これから出会うであろう、WAI-ARIA を必要とするような最もよくあるパターンのうちのいくつかを知るのに十分な情報も、お伝えしたはずです。

関連情報
----

* ARIA のステートとプロパティ: すべての aria-\* 属性
* WAI-ARIA ロール: ARIA のロールと MDN で扱うロールの分類
* ARIA in HTML (W3C): HTML の部品の各々について、どのアクセシビリティ（ARIA）の意味論がその部品に対してブラウザーにより暗黙裡に設定されるのか、そして、追加の意味論が必要な場合にはどの WAI-ARIA 機能をその部品に設定しうるのか、ということを定義するものです。
* Deque 大学のコードライブラリー — WAI-ARIA 機能を使ってアクセス可能にしてある複雑な UI コントロールを見せてくれる、実に有用かつ実践的な例からなるライブラリです。（英語）
* WAI-ARIA のオーサリングプラクティス — W3C による非常に詳細なデザインパターンです。異なる種類の複雑な UI コントロールを、WAI-ARIA 機能を用いてアクセス可能にしつつ、実装する方法を説明しています。（英語）
* 前のページ
* Overview: Accessibility
* 次のページ


HTML: アクセシビリティの基礎 - ウェブ開発を学ぶ

HTML: アクセシビリティの基礎
=================

* 前のページ
* Overview: Accessibility
* 次のページ

正しい HTML 言語の要素を常に正しい目的のために使用するようにするだけで、多くのウェブコンテンツをアクセシビリティに対応させることができます。この記事では、アクセシビリティを確実にするために HTML を使用する方法について詳しく見ていきます。

|  |  |
| --- | --- |
| 前提知識: | 基本的なコンピュータの知識、HTML に関する基本的な理解（HTML 概論を参照）、アクセシビリティとは何かに関する理解。 |
| 目的: | HTML のうち、どの機能にアクセシビリティ上の利点があるのか、また、自身のウェブドキュメントでそうした機能を適切に使うにはどうしたらよいのか、ということに精通すること。 |

HTML とアクセシビリティ
--------------

HTML について学習を進めるのにつれて — 資料をたくさん読んだり、たくさんの例を見たりするのにつれて — 共通の主題を繰り返し見続けることになるでしょう。つまり、意味的な（セマンティックな）HTML を使うことの重要性という主題です（これは、POSH すなわち Plain Old Semantic HTML（簡潔な昔ながらの意味的 HTML）と呼ばれることがあります）。これが意味することは、できる限り、ふさわしい HTML 要素をふさわしい目的に使う、ということです。

これが何故それほど重要なのか、不思議に思うかもしれません。何しろ、CSS と JavaScript の組み合わせを使って、ほぼすべての HTML 要素を、どのような仕方であれ望みどおりに振る舞わせることができるわけですから。たとえば、サイト上で動画を再生するためのコントロールボタンを、次のようにマークアップすることもできます。

```html
<div>動画を再生する</div>
```

けれども、後にさらに詳しく見るとおり、この役割にふさわしい要素を使うことには、とても意味があります。

```html
<button>動画を再生する</button>
```

HTML の `<button>` は、ある種の適切なスタイルが（おそらくそのスタイルを上書きしたいと思うでしょうが）既定で適用されているだけでなく、組み込みのキーボードアクセシビリティも備えています。つまり、ボタン同士の間を `Tab` で移動できますし、`スペース`、`リターン`、`Enter` を使ってボタンをアクティブにできます。

もしプロジェクトの最初から首尾一貫して意味的な HTML を書くならば、意味的な HTML を書く方が非意味的な（駄目な）マークアップを書くよりも長くなったりはしません。それに、意味的な HTML には、アクセシビリティ以外の他の利点もあります。

1. **より開発しやすい** — 上述のとおり、ある種の機能がただで手に入りますし、それに、より理解しやすいという点はまず間違いないところです。
2. **モバイル機器に関して、より優れている** — 意味的な HTML は非意味的なスパゲッティ・コードよりも、ファイルサイズの点でほぼ間違いなく軽量ですし、レスポンシブにするのも簡単です。
3. **SEO に関しても良好である** — 検索エンジンは、非意味的な `<div>` などに含まれるキーワードよりも、見出しやリンクなどの中のキーワードの方に重みを持たせているので、ドキュメントが顧客に見つけてもらいやすくなるでしょう。

それでは、ここからアクセシブルな HTML をより詳しく見てゆきましょう。

**メモ:** 自分のローカルコンピューターにスクリーンリーダーを用意することは良い考えです。そうすれば、以下に示す例について、ある程度のテストができます。より詳しくは、スクリーンリーダーを参照してください。

良いセマンティクス
---------

良いセマンティクスの重要性について、そして、ふさわしい役割にふさわしい HTML 要素を使うべきである理由については、すでに述べました。このことは無視してはなりません。なぜなら、適切に扱わないとアクセシビリティがひどく損なわれてしまう主な箇所のうちの一つだからです。

ウェブ上のどこかで、実は、人々は HTML のマークアップに関してとても変なことをしています。HTML の悪用のうちには、まだ完全に忘れ去られたわけではない過去の遺物的な慣行によるものもあり、ただ単純な無知によるものもあります。いずれにせよ、そうした駄目なコードは置き換えるべきです。

ときには、駄目なマークアップを取り去れる状況にいるとは限りません。自分で完全に制御しきれるわけではない、ある種のサーバーサイドフレームワークによって、生成されたページかもしれません。あるいは、自分のページ上に、自分が管理していない（広告バナーのような）第三者のコンテンツを含むかもしれません。

しかし、目標は「全てか無か」というものではありません。自分ができる改善のことごとくが、アクセシビリティの理念に役立つことでしょう。

### テキストコンテンツ

スクリーンリーダーのユーザーが得られる最良のアクセシビリティ支援の一つは、見出しや段落やリストなどの適切なコンテンツ構造です。きちんと意味を備えた例は、以下のようなものになるでしょう。

```html
<h1>見出し</h1>

<p>これは文書のうちの最初のセクションです。</p>

<p>ここにも、もう一つ段落を足すつもり。</p>

<ol>
  <li>ここには</li>
  <li>読んでもらいたいことの</li>
  <li>リストがあります。</li>
</ol>

<h2>下位見出し</h2>

<p>
  これは文書のうちの最初のサブセクションです。みんながこのコンテンツを見つけられるといいな!
</p>

<h2>2 番目の下位見出し</h2>

<p>
  これはコンテンツのうちで 2
  番目のサブセクションです。この前のものより面白いと思いますよ。
</p>
```

スクリーンリーダーを使って試せるように、より長いテキストのバージョンを用意してあります (good-semantics.html を参照)。これの全体をナビゲートしてみれば、これはとても見通しが得やすいものだということがわかるでしょう。

1. コンテンツの中を進んで行くのにつれて、スクリーンリーダーは各ヘッダを読み上げて、どれが見出しでどれが段落なのかといったことを知らせてくれます。
2. どのような速度が快適であるにせよ、その速度で進んでいけるように、スクリーンリーダーは各要素の後で停止します。
3. 多くのスクリーンリーダーでは、次の見出し / 前の見出しへとジャンプできます。
4. 多くのスクリーンリーダーでは、すべての見出しの一覧を取り出せます。それらの見出しを、特定のコンテンツを見つけるための手軽な目次のようにも使えます。

ときには、たとえば以下のように、体裁用の HTML や改行を使って見出しや段落などを書く人もいます。

```html
<span style="font-size: 3em">見出し</span><br /><br />
これは文書のうちの最初のセクションです。
<br /><br />
ここにも、もう一つ段落を足すつもり。
<br /><br />
1. ここには
<br /><br />
2. 読んでもらいたいことの
<br /><br />
3. リストがあります。
<br /><br />
<span style="font-size: 2.5em">下位見出し</span>
<br /><br />
これは文書のうちの最初のサブセクションです。みんながこのコンテンツを見つけられるといいな!
<br /><br />
<span style="font-size: 2.5em">2 番目の下位見出し</span>
<br /><br />
これはコンテンツのうちで 2
番目のサブセクションです。この前のものより面白いと思いますよ。
```

より長いバージョンをスクリーンリーダーで試してみれば（bad-semantics.html を参照）、とても良い体験が得られる、とはいかないことでしょう。スクリーンリーダーは、標識として使えるものが何も得られないので、有用な目次は取得できません。また、ページ全体を単一の巨大な塊として見ることになるので、ページ全体が一度にひとかたまりで読み上げられるだけなのです。

アクセシビリティ以外の他の問題もあります。たとえば、CSS を使ってコンテンツにスタイルをつけることや、あるいは、JavaScript でコンテンツを操作することが、より難しくなるのです。なぜなら、セレクターとして使える要素がないからです。

#### 明確な言葉を使う

使っている言い回しもアクセシビリティに影響を与えることがあります。一般に、過度に複雑ではない、明確な言葉を使うべきです。また、不必要な専門用語（ジャーゴン）や俗語を使わないようにしましょう。これは、認知的な障碍またはその他の障碍を抱える人たちの助けとなるだけではありません。母語以外で書かれたテキストの読者や、年少者の助けにもなりますし、実際のところあらゆる人の助けになります! それに加えて、スクリーンリーダーによって明確に読み上げられない言い回しや文字を使うことを避けるように努めるべきです。たとえば、以下のようなことです。

* やめられるものなら、ダッシュを使わないようにしましょう。「5–7」と書く代わりに「5 から 7」と書きましょう。
* 略語を展開しましょう。"Jan" と書く代わりに "January" と書きましょう。
* 少なくとも 1、2 回は、頭文字語を展開しましょう。そして `<abbr>` を使用して説明しましょう。
### ページレイアウト

古き悪しき時代には、HTML 表を使って（つまり、ヘッダー、フッター、サイドバー、主要コンテンツの列、などなどを含む、別々の表セルを使って）、ページレイアウトを作成していたものです。これは良い考えではありません。なぜなら、スクリーンリーダーが、こんがらがった読み上げを発する可能性が高いからです。特に、レイアウトが複雑で多くの入れ子になった表がある場合には、そうなりがちです。

table-layout.html の例を試してみてください。これは、以下のような感じになっています。

```html
<table width="1200">
  <!-- 主要な見出しの行 -->
  <tr id="heading">
    <td colspan="6">
      <h1 align="center">Header</h1>
    </td>
  </tr>
  <!-- ナビゲーションメニューの行 -->
  <tr id="nav" bgcolor="#ffffff">
    <td width="200">
      <a href="#" align="center">Home</a>
    </td>
    <td width="200">
      <a href="#" align="center">Our team</a>
    </td>
    <td width="200">
      <a href="#" align="center">Projects</a>
    </td>
    <td width="200">
      <a href="#" align="center">Contact</a>
    </td>
    <td width="300">
      <form width="300">
        <label
 >Search
          <input
 type="search"
 name="q"
 placeholder="Search query"
 width="300" />
        </label>
      </form>
    </td>
    <td width="100">
      <button width="100">Go!</button>
    </td>
  </tr>
  <!-- 間隔をあけるための詰め物の行 -->
  <tr id="spacer" height="10">
    <td></td>
  </tr>
  <!-- 主要なコンテンツと余談の行 -->
  <tr id="main">
    <td id="content" colspan="4">
      <!-- 主要なコンテンツがここに来る -->
    </td>
    <td id="aside" colspan="2" valign="top">
      <h2>Related</h2>

      <!-- 余談的コンテンツがここに来る -->
    </td>
  </tr>
  <!-- 間隔をあけるための詰め物の行 -->
  <tr id="spacer" height="10">
    <td></td>
  </tr>
  <!-- フッターの行 -->
  <tr id="footer">
    <td colspan="6">
      <p>©Copyright 1996 by nobody. All rights reversed.</p>
    </td>
  </tr>
</table>
```

スクリーンリーダーを使用してこれを操作しようとすると、おそらく見るべき表があることを指示します（ただし、スクリーンリーダーによっては、表のレイアウトとデータ表の違いを推測することができます）。その後、（使用している画面のリーダーによりますが）オブジェクトとしての表の中に降りて、その機能を別個に見てから、再び表の外に出て、コンテンツをナビゲートしなければならない可能性があります。

表レイアウトは過去の遺物です。CSSの対応がブラウザーに普及していなかったころは意味がありましたが、今ではスクリーンリーダーのユーザーを混乱させるだけです。さらに、表のソースコードにはより多くのマークアップが必要なため、柔軟性に欠け、メンテナンスが難しくなります。これらの主張は、以前の使い勝手とより現代的なウェブサイト構造の例を比較することで確認できます。このような例は、次のようになります。

```html
<header>
  <h1>Header</h1>
</header>

<nav>
  <!-- 主なナビゲーションはここです。 -->
</nav>

<!-- ここにページの主要コンテンツが来ます。 -->
<main>
  <!-- 主要コンテンツは記事を含みます。 -->
  <article>
    <h2>Article heading</h2>

    <!-- 記事の中身はここです。 -->
  </article>

  <aside>
    <h2>Related</h2>

    <!-- 余談の中身はここです。 -->
  </aside>
</main>

<!-- そしてここには、ウェブサイトの全ページを通じて使う主要なフッターが来ます。 -->

<footer>
  <!-- フッターの中身はここです。 -->
</footer>
```

より現代的な構造の例をスクリーンリーダーで試してみれば、もはやレイアウトマークアップが妨げになることもなく、コンテンツの読み上げを混乱させることもないとわかるでしょう。また、これは、コードサイズの点で、より無駄がなく、より小さくなっています。これが意味することは、コードの保守が容易になるということ、そして、ユーザーがダウンロードするのに帯域幅が小さくて済むということです（特に、接続が遅い人たちにとってはこれが効きます）。

レイアウトを作る際に考慮すべきもう一つの事柄は、上記の例に見られるように HTML の意味的要素を用いることです（コンテンツ区分を参照）。入れ子になった `<div>` 要素だけを使ってレイアウトを作ることもできますが、適切な区分要素を使って、主要なナビゲーション (`<nav>`) やフッター (`<footer>`) や繰り返し現れるコンテンツ単位 (`<article>`) などを囲う方が良いのです。これらの区分け要素は、いまナビゲートしている最中のコンテンツについての追加的な手がかりをユーザーに与えられるように、スクリーンリーダー（および他のツール）に追加的な意味（セマンティクス）を提供してくれます（スクリーンリーダーの対応とはどのようなものなのかについての考え方に関しては、Screen Reader Support for new HTML5 Section Elements を参照）。

**メモ:** 優れた意味づけと魅力的なレイアウトに加え、コンテンツは、そのソースの順序が論理的に意味をなしていなければなりません。後で CSS を使って常に好きな場所に配置することはできますが、最初にソースの順序を正しくしておくことで、スクリーンリーダーで読み上げられる内容が意味のあるものとなるのです。

### UI コントロール

UI コントロールとは、ウェブ文書内のユーザーが対話する主要な部分を意味します。最も一般的なのは、ボタン、リンク、およびフォームコントロールです。この節では、このようなコントロールを作成する際に注意すべき基本的なアクセシビリティの懸念について見ていきます。WAI-ARIAとマルチメディアに関するこの後の記事では、UIアクセシビリティの他の側面について見ていきます。

UI コントロールのアクセシビリティに対する一つの重要な側面は、ブラウザーが既定では 、UI コントロールをキーボードで操作できるようにしているということです。このことは、native-keyboard-accessibility.html の例 (ソースコード を参照) を用いて試せます。これを新規タブで開いて、タブキーを押してみてください。2、3 回押してみた後には、フォーカス可能な異なる要素の間をタブ・フォーカスが動き回り始めたのだと分かるはずです。どの要素にフォーカスが当たっているのかが分かるように、どのブラウザーでも、フォーカスの当たっている要素には、ハイライトされた既定のスタイルが付与されます (そのスタイルは、異なるブラウザー間では少し差があります)。

![3 つのボタンの中にそれぞれ "Click me!" "Click me too!" "And me!" というテキストが表示されています。3 つ目のボタンには、現在のタブのフォーカスを示す青い輪郭線があります。](/ja/docs/Learn/Accessibility/HTML/button-focused-unfocused.png)

**メモ:** 開発者ツールで、ページのタブ順序を示すオーバーレイを有効にすることができます。詳細な情報は、アクセシビリティインスペクター > タブ移動順序を表示 を参照してください。

その後、エンター / リターンキーを押すと、フォーカスの当たっているリンクをたどったり、ボタンを押したりすることもできますし（ボタンにメッセージ警告を出させるための JavaScript を含めておきました）、テキスト入力欄にテキストを入力するためのタイピングを開始することもできます。他のフォーム要素には別のコントロールがあります。たとえば、`<select>` 要素は、選択肢を表示させ、上下の矢印キーを用いて選択肢の間を行き来することができます。

**メモ:** 異なるブラウザーでは、異なるキーボードコントロールオプションを使用可能としている場合があります。さらに詳しいことは、ネイティブなキーボードアクセシビリティを使う を参照してください。

基本的に、適切な要素を使用するだけで、この動作を自由に得ることができます。

```html
<h1>Links</h1>

<p>This is a link to <a href="https://www.mozilla.org">Mozilla</a>.</p>

<p>
  Another link, to the
  <a href="https://developer.mozilla.org">Mozilla Developer Network</a>.
</p>

<h2>Buttons</h2>

<p>
  <button data-message="This is from the first button">Click me!</button>
  <button data-message="This is from the second button">Click me too!</button>
  <button data-message="This is from the third button">And me!</button>
</p>

<h2>Form</h2>

<form>
  <div>
    <label for="name">Fill in your name:</label>
    <input type="text" id="name" name="name" />
  </div>
  <div>
    <label for="age">Enter your age:</label>
    <input type="text" id="age" name="age" />
  </div>
  <div>
    <label for="mood">Choose your mood:</label>
    <select id="mood" name="mood">
      <option>Happy</option>
      <option>Sad</option>
      <option>Angry</option>
      <option>Worried</option>
    </select>
  </div>
</form>
```

これは、リンクやボタンやフォーム要素やラベルを適切に用いることを意味しています（フォームコントロール用の `<label>` 要素を含みます）。

しかし、やはり人々は HTML で何かと変なことをするものです。例えば、`<div>` を使用してマークアップされたボタンなどを時々見かけますね。

```html
<div data-message="This is from the first button">Click me!</div>
<div data-message="This is from the second button">Click me too!</div>
<div data-message="This is from the third button">And me!</div>
```

しかし、このようなコードを使用することはお勧めできません。`<button>` 要素を使用した場合に得られるはずだった、ネイティブのキーボードアクセシビリティを直ちに失い、さらにボタンが取得する既定の CSS スタイル設定も得られません。ボタン以外の要素をボタンに使用する必要がある場合は、`button` ロールを使用し、キーボードとマウスボタンの対応を含む、すべての既定のボタン動作を実装してください。

#### キーボードアクセシビリティを呼び戻すように盛り込む

そうした利点を呼び戻すように追加するには、ちょっとした作業が必要です（fake-div-buttons.html で例示的コードを試せます。ソースコード も参照してください）。ここでは、各ボタンに `tabindex="0"` という属性を付与することによって、見せかけの `<div>` ボタンにフォーカスを当てられるようにしました（タブキーを通じてのフォーカスを含みます）。

```html
<div data-message="This is from the first button" tabindex="0" role="button">
  Click me!
</div>
<div data-message="This is from the second button" tabindex="0" role="button">
  Click me too!
</div>
<div data-message="This is from the third button" tabindex="0" role="button">
  And me!
</div>
```

基本的に、`tabindex` 属性は、タブ移動可能な要素に、単に既定のソース順でタブ処理されるのではなく、独自のタブ順序（正の値の順序で指定されます）を持たせるためのものです。これは大きな混乱を発生させる可能性があるため、常に悪い考えです。本当に必要な場合にのみ使用してください。例えば、レイアウトがソースコードとはまったく異なる形で視覚的に物を示していて、より論理的に作業させたい場合などです。`tabindex` のオプションは、他にも 2 種類あります。

* `tabindex="0"` — 上記のとおり、この値によって、普通ならタブキーでの移動が可能ではない要素が、タブキーでの移動が可能となります。これは、`tabindex` の一番有益な値です。
* `tabindex="-1"` — これによって、普通ならタブキーでの移動が可能ではない要素が、（たとえば JavaScript を介して）プログラム的にフォーカスを得たり、あるいはリンクのターゲットとしてフォーカスを得たりすることが可能となります。

上記のような追加作業によって、タブキーでボタンに移動できるようにはなりますが、`Enter` / `リターン`キーを介してボタンをアクティブにすることはできるようになりません。それを可能とするには、以下のようなちょっとした JavaScript のごまかしを追加せねばなりません。

```js
document.onkeydown = (e) => {
  // The Enter/Return key
  if (e.key === "Enter") {
    document.activeElement.click();
  }
};
```

ここでは、キーボードのボタンが押されたことを検出するためのリスナーを `document` オブジェクトに追加しています。どのボタンが押されたかをイベントオブジェクトの `key` プロパティで調べます。押されたキーが `Enter`/`Return` なら、ボタンの `onclick` ハンドラーに格納された機能を `document.activeElement.click()` で実行しています。`activeElement` これは、現在ページ上でフォーカスされている要素を取得します。

これでは、機能を作り直すのに余計な手間がかかります。それに、他にも問題があるはずです。**そもそも、単にふさわしい要素をふさわしい役割に使うべきなのです。**

#### 意味の通るテキストラベル

UI コントロールのテキストラベルはあらゆるユーザーにとって大変有益ですが、そうしたラベルを適切なものにしておくことは、とりわけ、障碍のあるユーザーにとって重要です。

ボタンとリンクテキストのラベルが、理解可能であり、かつ弁別性のあるものになっていることを、確認すべきです。ラベルとして単に「ここをクリック」を使うのはいけません。なぜなら、スクリーンリーダーのユーザーは、ボタンとフォーム・コントロールの一覧をまとめ上げることがあるからです。以下のスクリーンショットは、Mac 上の VoiceOver によって一覧化されたコントロールを示しています。

![Mac の VoiceOver ソフトで掲載されているフォーム入力ラベルのリストです。このリストには、ボタン、テキストフィールド、リンクなどの様々なフォームコントロールに指定された "Happy menu item" のような無意味なラベルが含まれています。](/ja/docs/Learn/Accessibility/HTML/voiceover-formcontrols.png)

ラベルが存在している段落の文脈内においてラベルが意味をなすようにするだけでなく、文脈を離れてもラベルが意味をなすように (ラベルが単独で読まれても意味をなすように) してください。たとえば、以下のものは、良いリンクテキストの例を示しています。

```html
<p>
  クジラは本当にすごい生き物です。
  <a href="whales.html">クジラについてもっと知ってください</a>。
</p>
```

しかしこれは悪いリンクテキストです。

```html
<p>
  クジラは本当にすごい生き物です。クジラについてもっと知るには、
  <a href="whales.html">ここをクリックしてください</a>。
</p>
```

**メモ:** リンクの実装とベストプラクティスに関するさらなる情報を、ハイパーリンクの生成 という記事で知ることができます。また、いくつかの良い例と悪い例を、good-links.html と bad-links.html で見ることもできます。

フォームラベルも重要です。各フォーム入力欄に何を入力する必要があるのかについての手がかりを与えてくれるからです。以下のものは、十分に筋の通った例のように見えます。

```html
名前を入れてください: <input type="text" id="name" name="name" />
```

しかし、これは障碍を持ったユーザーにとってはあまり有益なものではありません。上の例では、ラベルが見えない場合に、ラベルとフォーム入力を一義的に関連づけ、どのように記入するかを明確にするものは何もありません。もし、ある種のスクリーンリーダーでこれにアクセスすると、「テキスト編集」という行に沿った説明しか与えられないかもしれません。

以下のものは、ずっと良い例です。

```html
<div>
  <label for="name">名前を入れてください:</label>
  <input type="text" id="name" name="name" />
</div>
```

このようなコードでは、ラベルが明確に入力欄と結びつけられることになります。説明は、「名前を入れてください: テキストを編集する」といった感じのものになるでしょう。

![テキスト入力フォームコントロールに「名前を記入してください」という良いフォームラベルが指定されています。](/ja/docs/Learn/Accessibility/HTML/voiceover-good-form-label.png)

追加のおまけとして、ほとんどのブラウザーにおいて、ラベルをフォーム入力欄に結びつけると、ラベルをクリックして当該フォーム要素を選択 / アクティブ化することができます。このため、入力欄に対して、より大きなヒット領域を与えることになり、入力欄が選択しやすくなります。

**メモ:** good-form.html と bad-form.html で、いくつかの良いフォーム例と悪いフォーム例を見られます。

適切なテキストラベルの重要性と、Firefox のアクセシビリティインスペクターを使用してテキストラベルの問題を調査する方法については、以下の動画でうまく説明されています。

アクセシブルなデータ表
-----------

基本的なデータ表は、たとえば以下のように、とても簡素なマークアップで書けます。

```html
<table>
  <tr>
    <td>Name</td>
    <td>Age</td>
    <td>Pronouns</td>
  </tr>
  <tr>
    <td>Gabriel</td>
    <td>13</td>
    <td>he/him</td>
  </tr>
  <tr>
    <td>Elva</td>
    <td>8</td>
    <td>she/her</td>
  </tr>
  <tr>
    <td>Freida</td>
    <td>5</td>
    <td>she/her</td>
  </tr>
</table>
```

しかしこれには問題があります。スクリーンリーダーのユーザーには、行または列をデータの集まりとしてまとめて関連づける手段が何もないのです。こうした関連づけを行うには、見出し行がどれなのか、見出し行は複数の行を統率しているのか、複数の列を統率しているのか、などといったことを知らねばなりません。こうしたことは、上記の表では、視覚的に行われる以外にありません（bad-table.html を参照して、その例をご自分で試してみてください）。

では、 パンクバンドの表の例 を見てみましょう。ここでは、多少のアクセシビリティ支援が機能していることが分かりますね。

* 表の見出しは、 `<th>` 要素を用いて定義されています。さらに、`scope` 属性を使って、その見出しが行に対する見出しなのか列に対する見出しなのかを指定することもできます。こうすると、スクリーンリーダーが一つの単位として処理できる、データの完全なグループが示されることになります。
* `<caption>` 要素と、`<table>` の `summary` 属性は、どちらも似たような役割を果たします。表に対する代替テキストとして機能し、スクリーンリーダーのユーザーに対して、表の中身についての有用で手短な要約を示すのです。一般的には `<caption>` 要素の方が、目の見えるユーザーもそのコンテンツにアクセスでき、有益な情報を探すことができるため、好ましいとされています。実のところ、両方が必要であるわけではありません。

**メモ:** アクセシブルなデータ表にまつわる更なる詳細は、HTML 表の発展的な機能とアクセシビリティ という記事を参照してください。

代替テキスト
------

テキストによるコンテンツは本質的にアクセシブルですが、マルチメディアコンテンツについては必ずしも同じことが言えるわけではありません。画像や動画のコンテンツは視覚障碍者には見えず、音声コンテンツは聴覚障碍者には聞こえません。動画と音声のコンテンツについては、アクセシブルなマルチメディア という記事で後に詳しく扱うことにしますが、本記事では、ごく普通の `<img>` 要素についてのアクセシビリティを見てゆきましょう。

accessible-image.html という簡単な例を書き上げました。これは、4 枚の同じ画像を含んでいます。

```html
<img src="dinosaur.png" />

<img
 src="dinosaur.png"
 alt="赤いティラノサウルスレックス。人間のように直立する二足歩行の恐竜で、腕は小さく、頭部は大きくて多くの鋭い歯があります。" />

<img
 src="dinosaur.png"
 alt="赤いティラノサウルスレックス。人間のように直立する二足歩行の恐竜で、腕は小さく、頭部は大きくて多くの鋭い歯があります。"
 title="The Mozilla red dinosaur" />

<img src="dinosaur.png" aria-labelledby="dino-label" />

<p id="dino-label">
  Mozilla
  の赤いティラノサウルスレックス。人間のように直立する二足歩行の恐竜で、腕は小さく、頭部は大きくて多くの鋭い歯があります。
</p>
```

1 枚目の画像は、スクリーンリーダーで閲覧したときに、実際のところ大した手助けをユーザーに与えてはくれません。たとえば VoiceOver は、"/dinosaur.png, image" と読み上げます。なんらかの手助けを提供しようとしてファイル名を読み上げるわけです。この例では、ユーザーは、少なくともこれがある種の恐竜なのだと知ることでしょうが、機械で生成されたファイル名とともにファイルが（たとえばディジタルカメラから）アップロードされる場合もよくありますし、そうしたファイル名は画像の中身に対する文脈を何も与えてはくれないでしょう。

**メモ:** これが、画像の中にテキストコンテンツを記載してはいけない理由です。スクリーンリーダーではアクセスできないからです。他にも、選択できない、コピー＆ペーストできないなどのデメリットがあります。とにかくやめておきましょう。

スクリーンリーダーは、2 枚目の画像に出くわすと、alt 属性を丸々読み上げます。つまり、「赤いティラノサウルスレックス。人間のように直立する二足歩行の恐竜で、腕は小さく、頭部は大きくて多くの鋭い歯があります」と読み上げます。

これは、いわゆる**代替テキスト**が利用できない場合に備えて、意味のあるファイル名を使用するだけでなく、可能な限り代替テキストが `alt` 属性で指定されていることを確認することの重要性を強調しています。

`alt` 属性のコンテンツは、常に画像とそれが視覚的に伝えるものを直接的に提供する必要があることに注意してください。alt は簡潔であるべきで、画像の中で伝達された情報のうち、周囲のテキストと重複していないものをすべて記載します。

単一の画像に対する `alt` 属性の内容は、文脈によって異なります。例えば、ふわふわの写真が Yuckymeat ドッグフードのレビューの隣にあるアバターであれば、`alt="Fluffy"` が適切です。もしその写真が動物保護団体の里親募集ページの一部であれば、画像から伝わる、これから犬を飼う人に関連する情報で、周囲のテキストに重複していないものを記載する必要があります。例えば、`alt="Fluffy, a tri-color terrier with very short hair, with a tennis ball in her mouth."` のような、より詳しい説明が適切でしょう。周囲のテキストにはフラッフィーの大きさや犬種が記載されている可能性が高いので、`alt` にはそのような情報は含まれません。しかし、犬の経歴には、親になる可能性のある人が知る必要のある毛の長さや色、おもちゃの好みなどは記載されていない可能性が高いので、記載されています。画像は屋外にいるのか、赤い首輪に青いリードを持っているのか？そのペットを採用する上で重要ではないので、含めません。画像が伝えるべき情報はすべて、サイトユーザーがアクセスでき、その状況に関連するものであり、それ以上のことはありません。短く、正確に、有益な情報を使用してください。

個人的な知識や余計な説明は、その画像を見たことがない人にとって有益なものではないので、ここには記載しない方が良いでしょう。ボールがフラッフィーのお気に入りのおもちゃであるとか、引用されたユーザーが画像からそれを知ることができないのであれば、それを記載しないでください。

考慮すべきことのひとつは、画像がコンテンツの中で意味をもっているのか、それとも純粋に視覚的な装飾であり、意味をもたないのか、ということです。もし装飾用であれば、`alt` 属性の値として空のテキストを書くか（空の alt 属性を参照）、CSS の背景画像としてページに記載するだけにした方がよいでしょう。

**メモ:** 画像の実装とベストプラクティスについての更なる多くの情報については、HTML の画像とレスポンシブ画像をお読みください。

文脈のある追加的な情報をどうしても提示したい場合、その情報は、画像の周囲のテキストの中か、あるいは、上記のように `title` 属性の内部に入れるべきです。この場合、ほとんどのスクリーンリーダーは、alt テキストと、title 属性と、ファイル名とを読み上げるでしょう。さらに、マウスオーバーしたときには、ブラウザーが title テキストをツールチップとして表示します。

![赤いティラノサウルス・レックスのスクリーンショット。マウスオーバー時にツールチップとして「The mozilla red dinosaur」のテキストが表示されます。](/ja/docs/Learn/Accessibility/HTML/title-attribute.png)

4 番目の方法についてもざっと見ておきましょう。

```html
<img src="dinosaur.png" aria-labelledby="dino-label" />

<p id="dino-label">The Mozilla red Tyrannosaurus…</p>
```

この場合、`alt` 属性をまったく使っていません。その代わり、画像についての説明を通常のテキスト段落として提示し、その段落に `id` を与え、そして、その `id` を参照するための `aria-labelledby` 属性を用いました。こうすると、スクリーンリーダーに、その段落をその画像についての代替テキスト / ラベルとして使わせることになります。これは、複数の画像に対して同じテキストをラベルとして使いたい場合に、とりわけ有用です（これは、`alt` ではできません）。

**メモ:** `aria-labelledby` は WAI-ARIA 仕様の一部です。これのおかげで開発者は、必要な箇所においてスクリーンリーダーのアクセシビリティを高めるために、自分のマークアップに追加的な意味（セマンティクス）を足すことができます。これがどのように機能するのかについての更なる情報を知るには、WAI-ARIA の基本 の記事をお読みください。

### figure と figcaption

HTML には、`<figure>` と `<figcaption>` という 2 つの要素があります。これらは、なんらかの種類の図（任意のものであってよく、必ずしも画像とは限りません）を、図のキャプション（説明文）と結びつけるためのものです。

```html
<figure>
  <img
 src="dinosaur.png"
 alt="Mozilla のティラノサウルス"
 aria-describedby="dinodescr" />
  <figcaption id="dinodescr">
    赤いティラノサウルスレックス。人間のように直立する二足歩行の恐竜で、腕は小さく、頭部は大きくて多くの鋭い歯があります。
  </figcaption>
</figure>
```

スクリーンリーダーによる図のキャプションとその図の関連付けの対応はまちまちですが、 `aria-labelledby` や `aria-describedby` は、もしキャプションがなければその関連を作成してくれるものです。とは言え、この要素構造は CSS スタイル設定に有益であり、加えてソース中の画像の横に説明文を配置する方法を提供します。

### 空の alt 属性

```html
<h3>
  <img src="article-icon.png" alt="" />
  ティラノサウルスレックス: 恐竜の王
</h3>
```

ページのデザインに画像が含まれることがありますが、その主な目的は視覚的な装飾です。上のコード例では、画像の `alt` 属性が空であることにお気づきでしょう。これは、スクリーンリーダーに画像を認識させるためですが、画像を説明しようとはしません（代わりに、「画像」または同様の表現をするだけです）。

`alt` を含めないようにする代わりに空の `alt` を用いる理由は、`alt` が与えられていない場合には多くのスクリーンリーダーが画像の URL を丸々全部発声するからです。上記の例において画像は、その画像が結びつけられている見出しに対する視覚的装飾として機能しています。このような場合、および、画像が単に装飾にすぎず中身の価値がない場合には、空の `alt` を `img` 要素に入れるべきです。別の選択肢は、`role="presentation"` という ARIA の `role` 属性を使うことです。こうすることによっても、スクリーンリーダーに代替テキスト（`alt` テキスト）を読み上げるのをやめさせることができます。

**メモ:** もし可能なら、単なる修飾であるような画像を表示するのには CSS を使うべきです。

リンクについての追加事項
------------

リンク（`<a>` 要素と `href` 属性）は、その使用方法によってアクセシビリティを向上させたり、害したりする可能性があります。既定では、リンクは外観上アクセシビリティが確保されています。リンクにより、ユーザーが文書内の様々なセクションにすばやく移動できるようにすることで、アクセシビリティが向上します。また、アクセシブルなスタイル設定が削除されたり、JavaScript で予期しない動作をさせられたりすると、アクセシビリティに害を与えることもあります。

### リンクのスタイル付け

既定では、リンクは色と text-decoration の両方で他のテキストと視覚的に異なります。既定ではリンクは青で下線、閲覧済みでは紫で下線、キーボードフォーカスを受けると focus-ring が付きます。

色は、リンクとそうでないコンテンツを判別する唯一の方法として使用すべきではありません。リンクテキストの色は、すべてのテキストと同様に、背景色と大きく異なっていなければなりません（a 4.5:1 contrast (en-US)）。さらにリンクは、リンクしていないテキストと視覚的に大きく異なる必要があり、リンクテキストと周囲のテキスト、既定値、訪問済み、フォーカス/アクティブの各状態間のコントラストは最低 3:1、それらすべての状態と背景色のコントラストは 4.5:1 が要求されています。

### `onclick` イベント

アンカータグは `onclick` イベントでよく悪用され、**href** に `"#"` や `"javascript:void(0)"` を設定して、ページの更新を行わないようにして擬似ボタンを作成することがあります。

これらの値は、リンクをコピーしたりドラッグしたり、リンクを新しいタブやウィンドウで開いたり、ブックマークしたり、JavaScriptでダウンロード中、エラー終了、無効になっているときに、予期しない動作を発生させます。また、支援技術（画面の内側から読み取るリーダーなど）に対しても、正しくない意味づけを伝えることになります。このような用途では、代わりに `<button>` を使用することを推奨します。一般に、アンカーは適切な URL を使用してナビゲーションする場合にのみ使用すべきです。

### 外部リンクと HTML 以外のリソースへのリンク

`target="_blank"` 宣言によって新しいタブやウィンドウで開かれるリンクや、`href` 値がファイルリソースを指すリンクは、リンクがアクティブになったときに起こる動作に関する説明を記載する必要があります。

弱視の人、画面の内側へ読み上げる技術を使っている人、認知能力に不安がある人は、新しいタブ、ウィンドウ、アプリケーションが不意に開かれたときに混乱するかもしれません。画面の内側へ古いバージョンの画面読み上げソフトでは、この動作が表示されないこともあります。

#### 新しいタブまたはウィンドウを開くためのリンク

```html
<a target="\_blank" href="https://www.wikipedia.org/"
 >Wikipedia (opens in a new window)</a
>
```

#### HTML 以外のリソースへのリンク

```html
<a target="\_blank" href="2017-annual-report.ppt"
 >2017 Annual Report (PowerPoint)</a
>
```

このようなリンクの動作を示すために、テキストの代わりにアイコンを使用する場合は、代替テキストを必ず含めてください。

* WebAIM: Links and Hypertext - Hypertext Links
* MDN WCAG を理解する、ガイドライン 3.2 の説明
* G200: Opening new windows and tabs from a link only when necessary | W3C Techniques for WCAG 2.0
* G201: Giving users advanced warning when opening a new window | W3C Techniques for WCAG 2.0
### スキップリンク

スキップリンク（skipnavとも呼ばれる）は、冒頭の `<body>` 要素にできるだけ近い位置に配置された `a` 要素で、ページの本文の冒頭にリンクするものです。このリンクによって、ウェブサイトのヘッダーや主要なナビゲーションなど、複数のページにわたって繰り返されるコンテンツを回避することができます。

スキップリンクは、スイッチ制御、音声コマンド、口棒／頭棒などの支援技術を使用して操作する人にとって特に有益で、繰り返されるリンクを移動する行為は手間のかかる作業となります。

* WebAIM: "Skip Navigation" Links
* How–to: Use Skip Navigation links - The A11Y Project
* MDN WCAG を理解する、ガイドライン 2.4 の説明
* Understanding Success Criterion 2.4.1 | W3C Understanding WCAG 2.0
### 近接性

アンカーを含む大量の対話型コンテンツが互いに視覚的に近い場所に配置されている場合、それらを分離するための空間を入れる必要があります。この空間は、手先の運動制御に問題があり、操作中に誤って誤った対話型コンテンツを作動させてしまう可能性がある人々にとって有益です。

空間は `margin` のような CSS プロパティを使用して作成することができます。

* Hand tremors and the giant-button-problem - Axess Lab
スキルをテストしましょう
------------

この記事の終わりまで来ましたが、最も重要な情報を覚えていますか？先に進む前に、スキルテスト: HTML アクセシビリティ (en-US) を参照して、この情報を覚えているかどうかを確認しましょう。

要約
--

これで、ほとんどの場合にアクセシブルな HTML を書くことについて、よく分かったでしょう。WAI-ARIA の基本の記事も、この知識の抜けを埋めてくれるでしょうが、本記事でもその基本には気を配ってきました。次は、CSS と JavaScript をよく使うか悪く使うかで、アクセシビリティがどのような影響を受けるのかを検討しましょう。

* 前のページ
* Overview: Accessibility
* 次のページ


アクセシブルマルチメディア - ウェブ開発を学ぶ

アクセシブルマルチメディア
=============

* 前のページ
* Overview: Accessibility
* 次のページ

アクセシビリティの問題を引き起こす他のカテゴリーは、マルチメディアでです。ビデオ、オーディオ、画像といったコンテンツは、支援技術 (assistive technologies) とユーザーが理解可能となる適切な代替テキストを必要とします。この記事ではその方法を説明します。

| 前提知識: | 基本的なコンピューターの知識、HTML 、CSS 、JavaScript に対する基本的な理解、 前回の記事 の理解 |
| --- | --- |
| 学習目標: | マルチメディアが引き起こすアクセシビリティの問題、およびその解決方法を理解すること |

マルチメディアとアクセシビリティ
----------------

このモジュールまで、様々なコンテンツに対してそのアクセシビリティを保証するために何が必要かを見てきました。シンプルな文章から始まって、データテーブル、画像、フォーム要素やボタンといったネイティブのコントロール、より複雑なマークアップ構造 (WAI-ARIA 属性) などです。

一方こちらの記事は、アクセシビリティの保証が難しい別のマルチメディアのコンテンツ群について扱っています。画像、ビデオ、`<canvas>` 要素、Flash 動画などは、スクリーンリーダーによる理解やキーボードによるナビゲーションが容易ではないため、私たちが手を差し伸べる必要があります。

ですが絶望はしないでください。ここではマルチメディアをアクセシブルにするために利用できる技術について紹介し、あなたの手助けをします。

シンプルな画像
-------

私達は既に HTML: アクセシビリティの基礎 で HTML 画像のシンプルな代替テキストについてカバーしました — 詳細を確認するために、そこに戻っても良いです。簡単に言うと、ビジュアルコンテンツとなり得るものは、スクリーンリーダーがユーザーのために読み上げることができるよう、代替テキストが利用可能であることを保証するべきです。

例えば:

```html
<img
 src="dinosaur.png"
 alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth." />
```

アクセシブルなオーディオとビデオコントロール
----------------------

ウェブベースのオーディオ/ビデオのコントロールを実装するのは問題にはならないはずですよね？調べてみましょう。

### ネイティブ HTML5 コントロールの問題

HTML5 の video と audio インスタンスは、ビルトインのコントロールと一緒に提供されており、何も設定せずにメディアの制御を行うことができます。例えば (`native-controls.html` ソースコードと実際の動作を参照):

```html
<audio controls>
  <source src="viper.mp3" type="audio/mp3" />
  <source src="viper.ogg" type="audio/ogg" />
  <p>
    Your browser doesn't support HTML5 audio. Here is a
    <a href="viper.mp3">link to the audio</a> instead.
  </p>
</audio>

<br />

<video controls>
  <source src="rabbit320.mp4" type="video/mp4" />
  <source src="rabbit320.webm" type="video/webm" />
  <p>
    Your browser doesn't support HTML5 video. Here is a
    <a href="rabbit320.mp4">link to the video</a> instead.
  </p>
</video>
```

control 属性は、あなたがメディアプレイヤーに対して期待する再生/一時停止ボタンやシークバーといった基本的なコントロールを提供します。Firefox と Chrome では次のように表示されます。

![Screenshot of Video Controls in Firefox](/ja/docs/Learn/Accessibility/Multimedia/native-controls-firefox.png)

![Screenshot of Video Controls in Chrome](/ja/docs/Learn/Accessibility/Multimedia/native-controls-chrome.png)

しかし、これらのコントロールには問題があります:

* たいていのブラウザーではキーボードでアクセスできません。つまりネイティブプレイヤー内でコントロール間をタブ移動できません。Opera と Chrome ではいくらか動きますが、理想的なものではありません。
* ネイティブコントロールは各ブラウザーによって異なるスタイルと機能が提供され、かつスタイリングすることができません。それは、サイトのスタイルガイドに従うのが容易ではないことを意味します。

これを改善するために、私たちは自分たちのカスタムコントロールを作成することができます。どのようにするのか見てみましょう。

### カスタム audio/video コントロール

HTML5 の video と audio は HTML メディア要素という API を提供しています。これは、あなたが定義したボタンや他のコントロールにカスタム機能をマップすることを可能にします。

上の video を例として、カスタムコントロールを追加してみましょう。

#### 基本のセットアップ

はじめに、custom-controls-start.html、 custom-controls.css, rabbit320.mp4、そして rabbit320.webm のコピーを取得し、あなたのハードドライブのディレクトリーに保存します

main.js というファイルを新規作成し、同じディレクトリーに保存します。

最初に、ビデオプレイヤーの HTML を見てみましょう。HTML の中は次のようになっています:

```html
<section class="player">
  <video controls>
    <source src="rabbit320.mp4" type="video/mp4" />
    <source src="rabbit320.webm" type="video/webm" />
    <p>
      Your browser doesn't support HTML5 video. Here is a
      <a href="rabbit320.mp4">link to the video</a> instead.
    </p>
  </video>

  <div class="controls">
    <button class="playpause">Play</button>
    <button class="stop">Stop</button>
    <button class="rwd">Rwd</button>
    <button class="fwd">Fwd</button>
    <div class="time">00:00</div>
  </div>
</section>
```

#### JavaScript の基本セットアップ

私たちは video の下にいくつかの簡単なボタンを挿入しました。もちろん、このままではこれらのコントロールは何もしません。機能を加えるためには JavaScript を使います。

まずはそれぞれのコントロールの設定を保持しておく必要があります。JavaScript ファイルの先頭に次のコードを追加してください:

```js
const playPauseBtn = document.querySelector(".playpause");
const stopBtn = document.querySelector(".stop");
const wdBtn = document.querySelector(".rwd");
const fwdBtn = document.querySelector(".fwd");
const timeLabel = document.querySelector(".time");
```

次に、video/audio プレイヤー自身の参照を取得する必要があります。次の行を先ほどのコードの下に加えてください:

```js
const player = document.querySelector("video");
```

これは `HTMLMediaElement` オブジェクトへの参照を保持します。このオブジェクトは、私たちのボタンに機能を紐づけるために使用可能ないくつかの便利なプロパティやメソッドを持っています。

私たちのボタンの機能を作る前に、カスタムコンロールの邪魔にならないようネイティブコントロールを削除しましょう。JavaScript の下に次のコードを追加してください:

```js
player.removeAttribute("controls");
```

最初から controls 属性を含めないようにするのではなく、わざわざこのようにするのには理由があります。もし JavaScript コードが何らかの理由で失敗しても、ユーザーは利用可能な何かしらのコントロールを使うことができるのです。

#### ボタンを紐つける

最初に、再生/一時停止ボタンをセットアップしましょう。次のように、再生と一時停止をシンプルな条件によって切り替えることで、この機能を実現できます。これをあなたのコードの下に追加しましょう:

```js
playPauseBtn.onclick = function () {
  if (player.paused) {
    player.play();
    playPauseBtn.textContent = "Pause";
  } else {
    player.pause();
    playPauseBtn.textContent = "Play";
  }
};
```

次に、ストップボタンを制御する次のコードを下に追加しましょう:

```js
stopBtn.onclick = function () {
  player.pause();
  player.currentTime = 0;
  playPauseBtn.textContent = "Play";
};
```

`HTMLMediaElement` には `stop()` 関数がありません。そこで `pause()` 関数を使用し、同時に `currentTime` に 0 を設定します。

続いて、巻き戻しと早送りボタンです。次のブロックをあなたのコードの下に追加してください:

```js
rwdBtn.onclick = function () {
  player.currentTime -= 3;
};

fwdBtn.onclick = function () {
  player.currentTime += 3;
  if (player.currentTime >= player.duration || player.paused) {
    player.pause();
    player.currentTime = 0;
    playPauseBtn.textContent = "Play";
  }
};
```

これらはとてもシンプルで、クリックされる度に `currentTime` 単に 3 秒を足すか引くだけです。実際のビデオプレイヤーでは、あなたはもっと手の込んだものを作りたいでしょう。

早送りボタンが押されたとき、 `currentTime` がメディアのトータルの `duration` よりも大きいか、そしてメディアが再生されていないかをチェックするという点についても気をつけてください。もしいずれかの条件が満たされているなら、ビデオが再生されていない時に早送りしようとしてもおかしくならないよう、単純にビデオを停止するか、ビデオの最後まで飛ばします。

最後に、再生時間を表示するために次の内容をコードの最後に追加します:

```js
player.ontimeupdate = function () {
  let minutes = Math.floor(player.currentTime / 60);
  let seconds = Math.floor(player.currentTime - minutes \* 60);
  let minuteValue;
  let secondValue;

  if (minutes < 10) {
    minuteValue = "0" + minutes;
  } else {
    minuteValue = minutes;
  }

  if (seconds < 10) {
    secondValue = "0" + seconds;
  } else {
    secondValue = seconds;
  }

  mediaTime = minuteValue + ":" + secondValue;
  timeLabel.textContent = mediaTime;
};
```

時間が更新される度に (1 秒に一度) 、この関数を実行します。これは秒として渡された currentTime の値 (秒で与えられる) から分と秒の数を算定するもので、もし分か秒の値が 10 以下であれば先頭に 0 を追加し、表示用の値を生成して時間ラベルに追加します。

#### 参考記事

ここでは、video/audio プレイヤーに対してどのようにカスタムしたプレイヤー機能を加えるかという基本的なアイデアが得られます。video/audio プレイヤーに対して、古いブラウザーでの Flash のフォールバックも含めて、より複雑な機能を加えるには、以下のリンク先を参照してください:

* Audio and video delivery (en-US)
* Video player styling basics (en-US)
* Creating a cross-browser video player (en-US)

さらに私たちは、あなたがどのようにしてオブジェクト指向システムを作ることができるかを見せるために高度な例も作りました。これは、ページ内のすべての video と audio プレイヤーを見つけ (どれだけ存在していたとしても)、私たちのカスタムコントロールを追加するものです。custom-controls-oojs を見てください (ソースコードも見てください) 。

オーディオトランスクリプト(Audio transcripts)
--------------------------------

聴覚障害の方にオーディオコンテンツを提供する場合、トランスクリプトのテキストを必ず用意する必要があります。これらは同じページの中に何らかの形で含んでも良いですし、リンクされた別ページに用意することもできます。

トランスクリプトを実際に作成する際は、次の選択肢があります。

* 商用サービス — プロフェッショナルに料金を払って文字起こししてもらうことができるでしょう。例として Scribie、Casting Words、Rev などの会社を見てください。色々見てアドバイスをもらい、あなたがうまく作業できる評判の良い会社を見つけてください。
* コミュニティ/草の根/自身の文字起こし — あなたがアクティブなコミュニティや職場のチームの一員であるなら、彼らに文字起こしのヘルプを頼むことができるでしょう。試しに自分自身で文字起こしに挑戦することもできます。
* 自動サービス — Trint のように利用可能な AI サービスがあります。サイトにビデオ/オーディオファイルをアップロードすれば、自動的にそれを書き起こします。YouTube では、自動的にキャプション/トランスクリプトを生成するように選択できます。生成されるトランスクリプトのクォリティは、どれだけ明瞭に話されているかに応じて大きく変わります。

人生の多くのものがそうであるように、あなたは支払った分相応のものを手に入れます。つまり、サービスが異なれば、トランスクリプト作成に要する時間と正確さが異なるということです。文字起こしをするために信頼できる会社や AI サービスにお金を払えば、正確なトランスクリプトを早く入手できるでしょう。料金を払いたくないのであれば、遅く、質の低いものになりやすいです。

オーディオリソースを公開するがトランスクリプトは後で提供する、という約束は良いものではありません。そのような約束は大抵守られず、ユーザーとの間にある信頼を損なってしまいます。もしオーディオが対面ミーティングやライブスピーチのようなものであるならば、それらが行われている間にノートを取り、オーディオと共に公開して、後からまとめ上げるということはできるでしょう。

### トランスクリプト例

もしあなたが自動サービスを使用しているならば、おそらくツールが提供しているユーザーインターフェイスを使用する必要があるでしょう。例えば、Wait, ARIA Roles Have Categories? を見て、 3 点メニュー (. . .) *> Show Transcript* を選択してください。トランスクリプトは別のパネルに表れるでしょう。

オーディオとそのトランスクリプトを表示するユーザーインターフェイスを自身で作成する場合、あなたのが考える形で作ることができますが、表示/非表示が可能なパネルを含むと良いかもしれません。私たちの audio-transcript-ui の例を見てください。 (ソースコード も見てください).

### オーディオの説明

オーディオに伴った映像がある場合、追加のコンテンツを描写するためにオーディオの説明を提供する必要があるでしょう。

多くの場合これはビデオの形を取り、この章の次のセクションで説明されるテクニックを使用してキャプションを埋め込むことができます。

しかし、いくつかのエッジケースもあります。例えば、スプレッドシートやグラフの資料を使用したミーティングの録音オーディオがあるかもしれません。その場合、それらの資料がオーディオとトランスクリプトとともに提供されていることを確認するべきであり、特にトランスクリプトの中でそれらの資料に言及されている箇所をリンクとすることが大事です。これは聴覚障害の方だけでなく、すべてのユーザーの助けになります。

**メモ:** オーディオトランスクリプトは、一般的に様々なユーザーグループを助けます。聴覚障害の人へオーディオに含まれたコンテンツにアクセスを提供するように、オーディオをダウンロードすることが困難な狭い帯域のユーザーのことを考えて見ましょう。パブやバーのような騒音の多い環境で、雑音のためにオーディオを聞くことが難しいユーザーのことも考えて見ましょう。

ビデオテキストトラック
-----------

聴覚障害者、視覚障害者、そして他のユーザー (狭い帯域のユーザーや、ビデオで使用される言語を話さないユーザー) にとってビデオをアクセシブルにするために、ビデオコンテンツにテキストトラックを含める必要があります。

**メモ:** テキストトラックは障害者だけでなく他のユーザーにとっても便利になる可能性があります。例えば、うるさい環境 (スポーツ中継を流している混雑したバーなど) にいるためにオーディオが聞こえないユーザーや、他の人を邪魔したくない静かな場所 (図書館など) にいるユーザーなどです。

これは新しいコンセプトではありません — テレビ放送では、かなり長い間クローズドキャプションを提供しています:

![Frame from an old-timey cartoon with closed captioning "Good work, Goldie. Keep it up!"](/ja/docs/Learn/Accessibility/Multimedia/closed-captions.png)

一方で、多くの国では英語の映画を自国の母語の字幕とともに提供していて、DVD では他の言語の字幕も利用可能となっています。

![An English film with German subtitles "Emo, warum erkennst du nicht die Schonheit dieses Ortes?"](/ja/docs/Learn/Accessibility/Multimedia/Subtitles_German.jpg)

テキストトラックには、目的に応じた様々な種類のものがあります。あなたが接する主な種類は、次のものです:

* キャプション — オーディオを聞くことができない聴覚障害者のためのものであり、話されている言葉、誰が話しているか、人が怒っているのか悲しんでいるのか、どのような雰囲気の音楽が流れているのかなど、場面に関する情報を含みます。
* 字幕 — 話されている言語を理解しないユーザーのための翻訳された音声の台本です。
* ディスクリプション (Descriptions) — ビデオを見ることができない視覚障害者のための描写を含みます。例えば、どのようなシーンに見えるか、などです。
* チャプタータイトル — メディアリソースを移動するユーザーを助けることを目的としたチャプターマーカーです。
### HTML5 ビデオテキストトラックの実装

HTML5 のビデオで表示されるテキストトラックは、WebVTT で記述される必要があります。これは、テキストの文字列とメタデータを含むテキストフォーマットであり、テキストが表示されるべき時間や、スタイル、ポジションといった情報まで含みます。これらの文字列はキュー (cues) と呼ばれます。

典型的な WebVTT ファイルは、次のようなものです:
```

WEBVTT

1
00:00:22.230 --> 00:00:24.606
This is the first subtitle.

2
00:00:30.739 --> 00:00:34.074
This is the second.

  ...
```

HTML のメディア再生と共に表示させるためには、次のことをする必要があります:

* .vtt ファイルとしてアクセス可能な場所に保存します。
* `<track>` 要素で .vtt へのリンクを設定します。 `<track>` は `<audio>` か `<video>` の間に設置する必要がありますが、すべての `<source>` 要素の後でなければいけません。 `kind` 属性を使い、キューが字幕、キャプション、ディスクリプションのどれなのかを指定します。さらに、 `srclang` を使って、字幕でどの言語が使用されているのかを伝えます。

例を見てみましょう:

```html
<video controls>
  <source src="example.mp4" type="video/mp4" />
  <source src="example.webm" type="video/webm" />
  <track kind="subtitles" src="subtitles\_en.vtt" srclang="en" />
</video>
```

これは、字幕が表示されたビデオとなり、次のようになります:

![Video player with standard controls such as play, stop, volume, and captions on and off. The video playing shows a scene of a man holding a spear-like weapon, and a caption reads "Esta hoja tiene pasado oscuro."](/ja/docs/Learn/Accessibility/Multimedia/video-player-with-captions.png)

詳細は Adding captions and subtitles to HTML5 video (en-US) を読んでください。あなたは、GitHub で GIan Devlin によって作られた例をこの記事と併せて見ることができます。(source ソースコード も見てください) この例では JavaScript を使用して、ユーザーが異なる言語の字幕を選択できるようになっています。字幕を表示するためには、"CC" ボタンをクリックして英語、ドイツ語、スペイン後のオプションを選択する必要があります。

**メモ:** テキストトラックは SEO でも役に立ちます。検索エンジンはテキストによって更新されるためです。検索エンジンは、テキストトラックによってビデオの途中に直接リンクすることさえできます。

その他のマルチメディアコンテンツ
----------------

上のセクションでは、あなたがウェブページに載せたいかもしれないすべての種類のマルチメディアコンテンツをカバーしていません。また、ゲーム、アニメーション、スライドショー、埋め込まれたビデオ、そして他の利用可能なテクノロジーを利用して作られたコンテンツを扱う必要があるかもしれません。例えば:

* HTML5 canvas
* Flash
* Silverlight

そのようなコンテンツには、アクセシビリティの懸念事項とケースバイケースで対応する必要があります。いくつかのケースでは、これはそれほど悪いことではありません。例えば:

* もし Flash や Silverlight のようなプラグイン技術を使用してオーディオコンテンツを埋め込んでいる場合、上の Transcript examples セクションで既に紹介したのと同じ方法でオーディオトランスクリプトを提供することができるでしょう。
* Flash や Silverlight のようなプラグイン技術でビデオコンテンツを埋め込んでいる場合、それらの技術で利用可能なキャプション/字幕の技術を利用することができます。例えば、 Flash captions、Using Timed Text Captions (Flash 用) 、 Playing Subtitles with Videos in Silverlight などを見てください。

しかし、他のマルチメディアはアクセシブルにすることがそう簡単ではありません。例えば、没入型 3D ゲームやバーチャルリアリティアプリを扱っている場合、そのような体験に対して代替テキストを提供することは非常に困難であるし、盲目のユーザーはそのようなアプリのターゲットに当てはまらないと考えるかもしれません。

しかしそのようなアプリでも、視力や色覚に問題を抱えるユーザーにとって認識できるよう、カラーコントラストや表示の明瞭さが十分であるかどうか、そしてキーボードからアクセス可能であるかを確かめることはできます。アクセシビリティは、100% を常に目指すというよりは、可能な限り行うものであるということを覚えておいてください。100% は大抵不可能なのです。

まとめ
---

このチャプターでは、マルチメディアにおけるアクセシビリティの関心ごとの要約をいくつかの実践的なソリューションと共に提供しました。

* 前のページ
* Overview: Accessibility
* 次のページ


チュートリアル - ゲーム開発

チュートリアル
=======

このページでは、さまざまなタイプのウェブゲームを効果的に作成するためのワークフローを紹介する、複数のチュートリアルシリーズを掲載しています。

純粋な JavaScript を使ったブロック崩しゲーム

このステップバイステップのチュートリアルでは、純粋な JavaScript を使用してシンプルなブレイクアウトクローンを実装します。その過程で、 `<canvas>` 要素を使用して、画像の描画や移動、衝突検出、制御機構、勝利と敗北状態などの基本的なゲームメカニズムを実装する基本を学びます。

Phaser を使用した 2D ブロック崩しゲーム

このステップバイステップのチュートリアルでは、前回のチュートリアルシリーズと同じブレイクアウトクローンを実装しますが、今回は、 Phaser HTML ゲームフレームワークを使って実装します。このチュートリアルでは、フレームワークを使用する際の基本的なこと（および利点）を、基本的なゲームの仕組みと一緒に教えることを目的としています。

端末の方向を使用した 2D 迷路ゲーム (en-US)

このチュートリアルでは、 HTML5 を使用して、 `<canvas>` 上の衝突検出やスプライトの配置などの基礎を取り入れた2D迷路ゲームを作成する方法を紹介します。これは、ゲームプレイを向上させるために、端末の方向とバイブレーション **API**を使用したモバイルゲームであり、 Phaser フレームワークを使用して構築されています。

2D platform game with Phaser

このチュートリアルシリーズは、 Phaser を使って、スプライト、衝突、物理、コレクションなどの基本的なプラットフォームゲームを作成する方法を紹介するものです。


ゲーム開発テクニック - ゲーム開発

ゲーム開発テクニック
==========

このページでは、オープンウェブ技術を使用してゲームを開発したい人のために、必要不可欠なコア技術をリストアップしています。

asm.js 用の非同期スクリプトの使用

特に中規模から大規模のゲームを作成する場合、非同期スクリプトは、ゲームの JavaScript をメインスレッドからコンパイルして、将来のゲーム実行時にキャッシュすることができるため、ユーザーにとって大幅なパフォーマンス向上となるため、活用することが不可欠なテクニックとなります。この記事では、その方法を説明します。

起動パフォーマンスの最適化 (en-US)

ゲームをすばやくスムーズに起動させ、ユーザーのブラウザーや機器をロックすることなく表示させる方法。

WebRTC のピアツーピアデータチャネルの使用

WebRTC では、音声と映像の通信に対応しているだけでなく、ピアツーピアのデータチャネルを設定して、プレイヤー間でテキストやバイナリーのデータを積極的に交換することができます。この記事では、これで何ができるかを説明し、これを簡単にするライブラリーを使用する方法を紹介します。

ウェブゲーム用の効率的アニメーション (en-US)

この記事では、携帯電話などのローエンド機器に対応しているウェブゲームで効率的にアニメーションを作成するためのテクニックとアドバイスを扱います。CSS の遷移と CSS アニメーション、そして `window.requestAnimationFrame` を含む JavaScript のループについて触れます。

ウェブゲームの音声

音声は、フィードバックや雰囲気を追加するものであり、ゲームにとって重要な要素です。ウェブベースの音声は急速に成熟していますが、まださまざまなブラウザーでの交渉が必要です。この記事では、ウェブゲームに音声を搭載するための詳細なガイドを提供し、可能な限り幅広いプラットフォームで現在動作しているものを見ていきます。

二次元の衝突検出

2D ゲームにおける衝突検出の簡潔な紹介。

タイルマップ (en-US)

タイルは、2Dゲームにおいてゲーム世界を構築するための非常に一般的な手法です。これらの記事は、タイルマップの紹介と、Canvas APIでタイルマップを搭載する方法を提供します。


ウェブ用のゲーム開発入門 - ゲーム開発

ウェブ用のゲーム開発入門
============

モダンウェブは、魅力的でクオリティの高いゲーム作りだけでなく、より重要な、そうしたゲームを配信するための、価値あるプラットフォームに急変身しました。

作成できるゲームの範囲は、デスクトップやネイティブ相当と同じレベルです。モダンウェブテクノロジーと最近のブラウザーがあれば、ウェブ用に魅力的で最高級のゲームを作ることも完全に可能です。かつて Flash® を使って作られたシンプルなカードゲームやマルチ・プレイヤーのソーシャルゲームについて述べているのではなく、スゲェ 3D アクションシューティングや、RPG や、その他について述べています。JavaScript JIT コンパイラーテクノロジーと新 API の充実したパフォーマンス改良のおかげて、ブラウザー (または HTML5 が動作する端末上) で動作するゲームを、妥協することなしに製作できます。

HTML ゲームプラットフォーム
----------------

本当に、ウェブをあなたのゲーム用のより優秀なターゲットプラットフォームだと考えることができます。言うなれば、"ウェブはプラットフォームです"。ウェブ プラットフォームのコアを見ていきましょう。

| 機能 | 技術 |
| --- | --- |
| **音声** | ウェブオーディオ API |
| **グラフィック** | WebGL (OpenGL ES
 2.0)
  |
| **入力** | タッチイベント,
 ゲームパッド, 端末センサー, WebRTC,
 全画面 API,
 ポインターロック API |
| **言語** | JavaScript (または C/C++ で
 Emscripten を使用して JavaScript へコンパイル)
  |
| **ネットワーク** | WebRTC や
 WebSocket |
| **ストレージ** | IndexedDB または「クラウド」 |
| **ウェブ** | HTML,
 CSS,
 SVG,
 Social API (およびその他多数)
  |

ビジネスの場合
-------

ゲーム開発者としては、個人でも大規模ゲームスタジオであっても、次のゲームプロジェクトでウェブをターゲットにすることの意味あいを知りたいでしょう。ウェブがどう便利になるか見ていきましょう。

1. ウェブのリーチは巨大です; つまりあらゆる場所です。HTML5 で製作されたゲームは、スマートフォン、タブレット、PC、スマート TV で動作します。
2. マーケティングと配信しやすさが改良されます。他の誰かのアプリストアで宣伝することに限定されません。その代わりに、他のメディア同様に ウェブ全体でゲームを広告・宣伝できて、ウェブに備わっているリンクやシェアのしやすさを利用して、新しい顧客にリーチできます。
3. 大事な事も管理できます: 支払いの事です。ゲームが他人のエコシステム内にあるだけで、収益の 30% 以上を渡す必要はありません。その代わりに、希望する金額で、気に入った支払い処理サービスを使用できます。
4. もっと管理について、希望するいかなる時にでも、ゲームを更新できます。他の会社の誰だかわからない人が、あなたの重大なバグ修正のリリースが今日になるか明日になるか決めるのを、ハラハラしながら承認待ちする必要はありません。
5. アナリティクスを管理しましょう! あなたがどのアナリティクスを必要とするかについて他人が決めるのに頼るのでなく、自分自身 (や最も気に入ったサードパーティを選んで) で、売上やゲームのリーチを集めることができます。
6. 顧客との関係 (CR) をより密接に、自分の方法で管理するようになります。アプリストアの限定された仕組みでフィルターリングされた顧客フィードバックはもうたくさんです。望む方法で、中間業者なしに、顧客を引きつけてください。
7. プレイヤーはゲームをいつでも、どこでもプレイできます。ウェブはユビキタスであるため、顧客は電話や、タブレットや、家のノート PC や、職場のデスクトップや、その他何によっても、ゲームの状況をチェック可能です。
ゲーム開発者用のウェブテクノロジー
-----------------

テクノ民のみなさん、ウェブがゲーム開発者のテーブルに運んでくる API を掘り下げましょう。こちらがウェブが実現できる味付けの全体リストです。

全画面 API

このシンプルな API では、あなたのゲームが全画面を占めることができます、その結果プレイヤーがアクションに没頭できます。

ゲームパッド API

ユーザーがあなたのゲームで動作するゲームパッドや他のゲームコントローラを使用できるようにしたい場合、この API が必要になるでしょう。

HTML と CSS

この 2 つのテクノロジーは一緒になって、ゲームの UI を作成、スタイル、レイアウトする事ができます。HTML の一部分は `<canvas>` 要素であり、これは 2 次元グラフィックスの 1 つの方法になります。

HTML オーディオ

`<audio>` 要素では、シンプルな SE と音楽を簡単に演奏できます。要望がもっと専門的な場合、リアルオーディオ処理のパワーのある ウェブオーディオ API を確認してください!

IndexedDB

ユーザーデータを、ユーザー自身のコンピューターや端末に保持するパワフルなデータストレージ API です。ゲームの状態とその他の情報をローカルに保存する良い方法で、必要な時に毎回ダウンロードする必要がなくなります。またユーザーがウェブに接続していない時 (何時間もずっと飛行機に載っているような時) であっても、ゲームを遊べるようにするのにも役立ちます。

JavaScript

JavaScript (ウェブで使われるプログラミング言語) は、モダンなブラウザーでは劇的に高速で、ずっと高速化されてきています。あなたのゲームのコードを記述するのにリンク先を使うか、既存のゲームを簡単に移植するには Emscripten や Asm.js などのテクノロジーの使用を見てみます。

ポインターロック API

ポインターロック API では、ゲームのインターフェイス内でマウスやその他のポインティングデバイスをロックし、その結果として絶対カーソル位置の代わりに、ユーザーが行っている事についての座標の差分を受け取ることができて、ユーザー入力がたまたま別のどこかに送られてしまい、その結果重要なアクションを見失うのを防ぎます。

SVG (Scalable Vector Graphics)

ユーザーのディスプレイサイズを気にすることなく、スムーズに拡大縮小するベクター画像を作ることができます。

型付き配列

JavaScript の型付き配列は JavaScript から生のバイナリーデータに対するアクセスを提供します。GL テクスチャ、ゲームデータまたはその他のものを、ネイティブな JavaScript 形式でなくても操作することができます。

Web Audio API

JavaScript コードからオーディオの再生、合成、操作の制御するこの API を使うと、素晴らしい音声効果を作成したり、リアルタイムに音楽の再生、操作をすることができます。

WebGL

ウェブコンテンツからハイパフォーマンスで、ハードウェア・アクセラレーションを行う 3D（または 2D）グラフィックスを作成することができます。これはウェブでサポートされている OpenGL ES 2.0 の実装です。

WebRTC

WebRTC (Real-Time Communications) API を使用すると、音声会議や二者間でほかのアプリケーションデータのやり取りなど、オーディオとビデオを制御することができます。モンスター攻撃中にプレイヤー同士で会話をさせたいですか？これはそんなあなたのための API です。

WebSocket

WebSocket API を使用すると、あなたのアプリやサイトをサーバーと接続し、リアルタイムにデータのやり取りを行うことができます。マルチプレイヤーゲームアクションやチャットサービスなどに最適です。

ウェブワーカー

Worker を使用すると、モダンでマルチコアなプロセッサを利用し、独自の JavaScript コードを実行して、バックグラウンドのスレッドを生成することができます。

XMLHttpRequest と ファイル API

XMLHttpRequest とファイル API を組み合わせることで、様々な種類のデータを送受信が可能になります ("XML"という言葉にとらわれないでください！)。これは、新しいゲームレベルやアートワークのダウンロードから、非リアルタイムのゲームステータス情報のやり取りに至るまで、あらゆることをするためのすばらしい方法です。


ゲーム開発のためのツール - ゲーム開発

ゲーム開発のためのツール
============

このページにはゲーム開発ツールに関する記事へのリンクがまとまっています。ゆくゆくはフレームワークやコンパイラー、デバッグ用ツールもカバーすることを目指しています。

asm.js

asm.js は極めて限定された JavaScript のサブセットで、ahead-of-time (AOT) コンパイラーで最適化されて、通常の JavaScript コードよりも極めて高速に動作します。これはもちろん、ゲーム用に優れています。

Emscripten

LLVM から JavaScript へのコンパイラーです。これを利用することで、C++ や LLVM バイトコードを出力する言語のコードを、高速に動作する JavaScript へコンパイル可能です。これはアプリをウェブに移植する優秀なツールです! 有用な Emscripten のチュートリアルはこちらです。 なお MDN にも Emscripten の記事を執筆中です。

Firefox プロファイラー

Gecko プロファイラーを利用すると、パフォーマンス上の問題を引き起こしている箇所の特定が容易になります。その結果あなたのゲームは最高速で動作できます。

Shumway

Shumway は Adobe Flash で作成されたものを JavaScript や WebGL などを用いてレンダリングします。これを利用することで Flash とオープンな Web 標準との間の溝を埋められます。この文書では Shumway の利用方法と、バグ修正にコントリビュートする方法について解説します。

ゲーム開発とデバッグのためのツールチェーン

通常のウェブアプリのデバッグとの違いや、ツールについて解説します。多くは開発ツールでカバーされますが、特に有用なツールチェーンのチュートリアルはこちらです。

* 基本的なツールの概要
* シェーダエディタ
* パフォーマンスツール


ビデオゲームの解剖学 - ゲーム開発

ビデオゲームの解剖学
==========

この記事では平均的なビデオゲームの中身とワークフローを技術的な観点、メインループがどう動くべきかに関して見ていきます。初心者が現代的なゲーム開発の海で、ゲーム制作に何が必要なのか、JavaScript のようなウェブ標準がツールとして寄与しているかを理解するのに役立ちます。ベテランのゲームプログラマーでウェブ開発を始めたばかりの方にも役立ちます。

表示し、受け入れ、翻訳し、計算し、繰り返す
---------------------

あらゆるビデオゲームのゴールはユーザーに状況を**表示**して入力を**受け入れ**てこの信号を**翻訳して**行動し、行動から得られる新しい状況を**計算**することです。ゲームはこうした段階を常に何度も何度も繰り返して、何かの条件が (例えば勝利や敗退や、あるいは終了して寝ること)起きるまで繰り返します。驚くことでなく、このパターンはゲームエンジンがプログラムされているさまに対応しています。

詳細な仕様はゲームに依存します。

ユーザー入力によって駆動するゲームもあります。「2 つの絵の違いを見つける」タイプのゲームを開発していると想像してみてください。このゲームはユーザーに 2 つの画像を\*\*表示します。**ユーザーのクリック(やタッチ)**を受け入れます**。入力を成功、失敗、一時停止、メニューのやりとりなどに**翻訳します。\*\*最後にその入力から起きて更新されるシーンを \*\*計算します。\*\*ゲームループはユーザー入力まで進んで、ユーザーが与えるまでスリープします。これは 1 ターンずつのアプローチ以上のもので、毎フレームごとの常時更新を求めず、プレイヤーが反応した時だけ更新します。

他のゲームはなるべく最小な個々のタイムスライス単位を管理します。上記と同じ原則が少しひねりを加えて適用されます。アニメーションの各フレームはサイクルを勧め、利用できる最初のターンでユーザー入力の変化が捉えられます。この毎フレームごとの実装モデルは**メインループ**と言います。ゲームループが時間ベースならば、これはシミュレーションが従うべき権威です。

しかし毎フレームの管理は不要かもしれません。ゲームループは違いを見つける例と同じで入力イベントに依存しているかもしれません。また入力と時間のシュミレーションの両方が必要かもしれません。その他のものに完全に依存するループかもしれません。

モダン JavaScript — 詳しくは次の節で述べますが — は効率よく、毎フレームで実行されるメインループを簡単に開発できます。もちろん、あなたのゲームではできるだけ最適化できます。あまり発生しないイベントにアタッチすべきだと思うならば、メインループから外れるのも (いつもではないにしろ) 良い考えです。

JavaScript でメインループを作る
---------------------

JavaScript はイベントとコールバック関数に対して最高の働きをします。 モダンなブラウザーはできるだけメソッドをちょうどそれらが必要になった時やアイドル状態の (もしくはほかのタスクをやっている) 時に呼び出そうとします。 それがどう素晴らしいアイデアなのかというと、あなたのコードを的確な瞬間にアタッチできるからです。こんな場合を考えてみましょう - あなたの関数が毎フレームごとに厳密な間隔で絶対に呼び出されなければならないか、もしくはほかの何かが起こってはじめて絶対に呼び出されなければならないとします。ブラウザーにいつ関数が呼び出されるかについてよりはっきりさせるということはブラウザーがそれをいつ呼び出すかを最適化することを許すことになります。また、それはひょっとしたらあなたの仕事をより簡単にするかもしれません。

いくつかのコードはフレーム毎に実行される必要があるかもしれませんので、なぜその関数をブラウザーの再描画スケジュール以外のものにアタッチする必要があるのでしょうか?ウェブでは、 ``window.requestAnimationFrame()`` がほとんどのよくプログラミングされた毎フレームメインループの基礎になるでしょう。コールバック関数はそれ自身が呼び出されたときそこに渡されなければなりません。そのコールバック関数は次の再描画までの適切な時間で実行されます。単純なメインループの例を見てみましょう。
```

window.main = function () {
  window.requestAnimationFrame( main );

  // あなたのメインループが必要な事なんでも
};

main(); //メインループ開始
```

**メモ:** ここで議論されている`main()` 関数はそれぞれ、ループコンテンツを行う前に新しい`requestAnimationFrame`をスケジュールしています。これは間違っているのではありませんし、ベストプラクティスを考慮しています。前もって次の `requestAnimationFrame` を呼び出すことはブラウザーが適宜それを正しい時に受け取ることを保証します。たとえあなたの現在のフレームが VSync window を見失ってしまったとしてもです。

上のコードは 2 つの宣言があります。 最初の宣言はある関数をグローバル変数として `main()` と呼ばれる関数を作成します。この関数はいくつかの仕事をして同時にブラウザーにそれ自身を `window.requestAnimationFrame()` を使って呼ぶように言います。ふたつ目の宣言は `main()` 関数 - それは最初の宣言で定義されたのですが、それを呼びます。`main()` は 2 つ目の宣言で一度だけ呼ばれて毎回それを呼ぶ度に次のフレームでやるべきことのキューに配置していくので、`main()` はあなたのフレームレートと同期します。

もちろん、このループは完全ではありません。変更すべき点を議論する前に、既になにをちゃんとやっているのか議論させてくださいね。

メインループをブラウザーがディスプレイを描画するタイミングで実行することであなたのループはブラウザーが描画したいと思ったタイミングと同じ頻度で実行されることが可能になります。あなたは毎アニメーションフレームごとにコントロールできるようになりました。同時に、どうこれがとても簡単なのかというと、 `main()`だけがループされる関数だからです。First Person Shooter (もしくはそれに類するゲーム)だと 1 フレームごとに 1 回新しいシーンを表示します。これ以上にスムーズでレスポンシブにしようがありません。

だからといってすぐにアニメーションは 1 フレームごとにコントロールが必要だと考えないでください。簡単なアニメーションは (たとえ GPU アクセラレートされていたとしても) CSS アニメーションやブラウザーについてくるほかのツールで簡単に実行することができます。それらはたくさんあり、あなたの開発をより簡単にしてくれるでしょう。

Javascript でマシなメインループを作る
------------------------

明らかに 2 つ問題が上記のメインループにはあります。 `main()` が ``window`` オブジェクトを汚染している(そこにはすべてのグローバル変数が格納されているのですが)ことと、すべてのタブが閉じられるか更新されるかするまでループを止めることができません。ひとつつ目の問題に関しては、もしメインループがただ走るだけで簡単に(直接)それにアクセスする必要がないのであれば、それを Immediately-Invoked Function Expression (IIFE) として作ることができます。
```

/*
* セミコロンで始めるというのは以下の例では automatic semicolon insertion (ASI) によります。
* ブラウザーが間違ってこの例全体を前の行から続いていると判断するかもしれません。
* このセミコロンがあることでたとえ前の行が空でなかったり
* ちゃんと終わってなかった場合でも新しい行が始まっていることを示すことができます
*/

;(function () {
  function main() {
    window.requestAnimationFrame( main );

    // メインループの中身
  }

  main(); // ループを開始する
})();
```

ブラウザーがこの IIFE に出くわすと、メインループを定義してすぐさま次のフレームにキューします。これで何のオブジェクトにもアタッチされなくなり、`main()` (もしくは `main()` のためのメソッド) は残りのアプリケーションで使用可能な未使用の名前になり、何か別に定義してもよくなりました。

**メモ:** 実際は、次の `requestAnimationFrame()` を if 構文で防ぐほうがより一般的で、`cancelAnimationFrame()` を呼ぶことはそれよりも一般的ではありません。

2 つ目の問題 - つまり、メインループを止めるという問題に関しては、`main()` を ``window.cancelAnimationFrame()`` によって呼び出しをキャンセルする必要があるでしょう。あなたは一番最後に `requestAnimationFrame()` が呼ばれたときに `cancelAnimationFrame()` に `requestAnimationFrame()` で得た ID トークンを渡す必要があります。 こんな風な場合を想定してください - あなたのゲームの関数と変数が `MyGame` と呼ばれる名前空間に備え付けられています。先述の例を拡張すると、メインループはこんな風になります。
```

/*
* セミコロンで始めるというのは以下の例では automatic semicolon insertion (ASI) によります。
* ブラウザーが間違ってこの例全体を前の行から続いていると判断するかもしれません。
* このセミコロンがあることでたとえ前の行が空でなかったり
* ちゃんと終わってなかった場合でも新しい行が始まっていることを示すことができます
*
* MyGame は前もって定義されてるとします。
*/

;(function () {
  function main() {
    MyGame.stopMain = window.requestAnimationFrame( main );

    // メインループの中身.
  }

  main(); // ループ開始
})();
```

`MyGame` 名前空間に宣言された変数があって、それを `stopMain` と名付けて、それにはメインループの一番最後に `requestAnimationFrame()` を呼び出した時に返された ID が含まれています。我々はいつでもメインループを止めることができます - ブラウザーに私たちのトークンと関連するリクエストをキャンセルすることで。
```

window.cancelAnimationFrame( MyGame.stopMain );
```

メインループをプログラミングするカギとなるのは - JavaScript ではですが - それを何かしらのあなたのアクションを駆動しているようなイベントにアタッチし、どんなふうに色んなシステムが相互作用にかかわっているかに注意することです。たくさんのコンポーネントがたくさんの違うタイプのイベントによって駆動しているかもしれません。不必要に複雑だという風に感じるかもしれませんが、それこそが良い最適化かもしれませんよね(必ずしもそうじゃないかもしれませんけど、もちろん)。大事なのはあなたは典型的なメインループをプログラムしていないということです。Javascript では、あなたはブラウザーのメインループを使って効率的にやろうという風に挑戦できます。

JavaScript でもっと最適化されたメインループを作る
------------------------------

究極的には JavaScript ではブラウザーはそれ自身のメインループを走らせて、あなたのコードはそれのいくつかの段階に存在します。これからのセクションではメインループがブラウザーからコントロールを奪い取らないようにすることについて記述します。これらのメイン関数は自身 を`window.requestAnimationFrame()` にアタッチし、`window.requestAnimationFrame()` はブラウザーに次に来るであろうフレームへのコントロールを要求します。どうやってこれらの要求をブラウザーのメインループと関連付けるかはブラウザー任せです。W3C の requestAnimationFrame の仕様はいつ requestAnimationFrame コールバックが実行されるのか厳密に定義していません。これはいいことです - なぜかというと、そうすることでブラウザのベンダーが自由に最適だと感じる解決策を実験し、何回も微調整することができるからです。

最近の Firefox と Google Chrome (と、たぶん他のも) のバーションはフレームのタイムスライスの初めで `requestAnimationFrame` コールバックをメインスレッドに接続***しよう***とします。ブラウザーのメインスレッドはしたがってこんな風に見***せよう***とします。

1. 新しいフレームを始める (一方、前のフレームはディスプレイによって制御されます)
2. `requestAnimationFrame` コールバックのリストを通ってそれらを invoke します
3. 上記のコールバックがメインスレッドのコントロールをやめた時、ガベージコレクターを実行して、フレームごとのタスクを実行します
4. ブラウザーの Sleep (訳注: nap と書かれていますが、日本語にそれに対応したプログラミング界隈で使われる言葉が無かったので Sleep と訳しました) を妨げない限りモニターがイメージ (VSync) の準備ができるまで Sleep し、繰り返す。

こんな風に考えることもできます - リアルタイムアプリを開発していて、何かタスクを限られた時間のうちにこなさなければならない、という風に。上のすべてのステップは実行を 60Hz のディスプレイの描画に追いつくように 16.5ms 以内に終わらせなければなりません。ブラウザーはあなたのコードをできるだけ早く最大の計算時間を与えようと invoke します。メインスレッドはしばしばメインスレッド上にない仕事 (例えばラスタライズや WebGL のシェーダーなど) を始めるかもしれません。重たい計算は Web Worker や GPU で同時に実行されるかもしれません - というのは、ブラウザーはメインスレッドを使ってガベージコレクションやそれにまつわるタスクや、非同期なイベントを管理するからです。

限られた時間の中での話をしましたが、たくさんのウェブブラウザーには *High Resolution Time* というツールがあります。`Date` オブジェクトはもはやタイミングオブジェクトとして認識されていません - なぜかというと、不正確でシステムクロックによって書き換えられてしまうからです。High Resolution Time は一方で `navigationStart` (前のドキュメントがアンロードされた時) からのミリ秒を数えます。この値は小数点値として誤差 1000 分の 1 ミリ秒の正確さで返ってきます。``DOMHighResTimeStamp`` という風に馴染みが深いですが、実際は浮動小数点値として考えてください。

**メモ:** いくつかのシステム(ハードウェアであれソフトウェアであれ)のうちマイクロ秒の正確さが担保されていないものは最低ミリ秒単位の正確さが許容されています。しかし、可能であれば 0.001 ミリ秒の正確さを提供します。

この値はそれ自体ではとても有効ではありません。なぜなら、無用なイベントに対しての相対値だからです。しかし、他のタイムスタンプから引き算されることで正確にそれら 2 つのイベント間の時間がいくらなのか決定することができます。これらのタイムスタンプを習得するには`window.performance.now()` を呼んで、結果を変数として格納してください。
```

var tNow = window.performance.now();
```

メインループの話に戻りましょう。いつメイン関数が invoke されるのか知りたいとしばしば思うでしょうね。これはよくあることなので、`window.requestAnimationFrame()` は常に`DOMHighResTimeStamp` をコールバックに引数として実行されるたびに渡しています。こうしてもう一つ先述のメインループが改良されました。
```

/*
 * セミコロンで始めるというのは以下の例では automatic semicolon insertion (ASI) によります。
 * ブラウザーが間違ってこの例全体を前の行から続いていると判断するかもしれません。
 * このセミコロンがあることでたとえ前の行が空でなかったり
 * ちゃんと終わってなかった場合でも新しい行が始まっていることを示すことができます
 *
 * MyGame は前もって定義されてるとします。
*/
;(function () {
  function main( tFrame ) {
    MyGame.stopMain = window.requestAnimationFrame( main );

    // メインループの中身
    // tFrameは"function main ( tFrame )"から来て, rAFによって提供され、ここで DOMHighResTimeStamp になります
  }

  main(); // ループ開始
})();
```

いくつか他に最適化することもできますが、あなたのゲームが何を達成しようとしているかによって全然違います。あなたのゲームのジャンルがきっと教えてくれるでしょうが、まずもってそんなことよりももっと微妙なものになるでしょう。キャンバスに 1 ピクセルごとに描画することもできますし、DOM 要素を (複数の WebGL キャンバスで透明な背景を持ったものとかでもやろうと思えば)複雑な階層へとレイヤー化することもできます。それぞれの道程に一つずつの条件と制約があるでしょう。

さあ決断の時は...来たれり
--------------

メインループに関しては難しい決断をしなくてはなりません。どんな決断かというとどうやって正確な時間の経過をシミュレーションしようかということです。もし毎フレームコントロールが必要なら、どれくらいの頻度であなたのゲームが更新され、描画されるかを決定しなければなりません。ひょっとしたら更新と描画を別の頻度でしたいとさえ考えるかもしれません。またもう一つ考えないといけないのは、あなたのゲームがユーザーのシステムがゲームの仕事量に及ばない場合にどうやったらいい感じに失敗するだろうかということです。こういう場合を考えてみましょう - ユーザーのインプットを扱ってゲームの状態を描画するたびに更新するとします。以下に展開していきましょう。

**メモ:** メインループがどうやって時間を扱うかを変更することはデバッグ地獄です。どんな場合でも。要求を注意深く考慮してからメインループに取り掛かりましょう。

### ブラウザーゲームはほとんどの場合こんな感じになっているべきだ

あなたのゲームがあなたがサポートしているどんなハードウェアでも最大のフレッシュレートを叩きだせるのであれば、とっても簡単です。単に更新し、レンダリングして、VSync まで何もしなければいいのです。
```

/*
* セミコロンで始めるというのは以下の例では automatic semicolon insertion (ASI) によります。
* ブラウザーが間違ってこの例全体を前の行から続いていると判断するかもしれません。
* このセミコロンがあることでたとえ前の行が空でなかったり
* ちゃんと終わってなかった場合でも新しい行が始まっていることを示すことができます
*
* MyGame は前もって定義されてるとします。
*/

;(function () {
  function main( tFrame ) {
    MyGame.stopMain = window.requestAnimationFrame( main );

    update( tFrame ); //更新メソッドを呼びます。私たちのケースでは、rAFのタイムスタンプを渡します。
    render();
  }

  main(); // ループ開始
})();
```

もし最大リフレッシュレートに達しないのであれば、品質設定が適用され、決められた時間内に実行できるようにします。これのもっとも有名な例は id Software の Rage です。このゲームはユーザーからのコントロールを取り除いて計算時間をだいたい 16 ミリ秒 (もしくはだいたい 60fps) に保ちます。もし計算時間がもっとかかるのであれば、レンダリング解像度は低くなり、テクスチャや他のアセットがロードしたり描画するのを失敗し…といった感じです。この例は(ウェブではありませんが)以下のような想定とトレードオフを考えることができます。

* 毎フレームごとのアニメーションはユーザーの入力によって占められています。
* どんなフレームも補間される(推測される)必要がありません。なぜなら、それぞれの描画はそれ自身の更新を所有しているからです。
* シミュレーションシステムは基本的にフルに更新しても 16 ミリ秒間隔だと想定している。
* ユーザーに品質設定をコントロールさせるのはクソだ。
* モニターは色んなレートで入力される: 30 FPS, 75 FPS, 100 FPS, 120 FPS, 144 FPS, などなど。
* 60FPS を実現できないシステムは最適なスピードでゲームをプレイするための視覚品質を失う(品質があんまりにも低くなると、ついには完全に落ちる)
### 様々なリフレッシュレートを制御するためにできる他の方法

他にも問題を追跡するための方法が存在します。

よくある手法の一つが、定常的な頻度でシミュレーションを更新して、できるだけ(もしくは最低限)実際のフレームを描画することです。この更新方法はユーザーが何を見ているのか気にせずにループを続けることができます。描画メソッドは更新が起きた時に一番最後の更新を視覚化することができます。描画メソッドはいつそれを視覚化すべきかと一番最後の更新のシミュレーション時間を知っているので、それらしいフレームを予測してユーザーに描画してみせることができます。本当の更新ループの頻度よりも多いか(もしくは少ないか)は問題ではありません。更新メソッドはチェックポイントをシステムが許す限り頻繁に作って、レンダリングメソッドは短い時間でそれらが指すものを描画します。更新メソッドを分割する方法はウェブスタンダードにたくさんあります。

* `requestAnimationFrame` で描画し、`window.setInterval` または `window.setTimeout`　で更新する。
    + これはフォーカスされていないときや最小化されている時でも処理時間を使い、メインスレッドを占有して、ひょっとしたら昔のゲームのループの遺物なのかもしれません(が、簡単です)
* `requestAnimationFrame` で描画し Web Worker の `setInterval` か `setTimeout` で更新する。
    + 上述のものと同じですが、メインスレッドを占有しない (または、メインスレッドがこれ自体を占有しない) 点で違います。これはより複雑な解決策で、単純な更新に対してはオーバーヘッドが大きすぎるかもしれません。
* `requestAnimationFrame` で描画し、それを Web Worker を poke (訳注: 突っつくぐらいの意味ですが、invoke のような意味で使われているのではないかと思われます)するために使う (Web Worker は更新メソッドをたくさん有していて、数 tick で計算することができます)。もしあればですが。
    + これは `requestAnimationFrame` が呼ばれるまで Sleep し、メインスレッドを汚染することがありません。加えて、古臭いメソッドに頼らなくて済みます。繰り返しになりますが、これは上記二つの方法よりももう少し複雑でそれぞれの更新を始めることはブラウザーが rAF コールバックを実行するまでブロックされます。

これらの方法はそれぞれ似たようなトレードオフがあります:

* ユーザーはフレームのレンダリングをスキップするかもしくはパフォーマンス依存で臨時の 1 フレームを補完することができます。
* You can count on all users updating non-cosmetic variables at the same constant frequency minus hiccups.
* 今まで見てきたような基本的なループよりもプログラムがずっと複雑。
* ユーザーの入力が次の更新まで完全に無視される (たとえユーザーが速いデバイスを持っていても)。
* mandatory な補間はパフォーマンスを犠牲にします。

更新と描画をばらばらにした例は次のようになるはずです。デモンストレーションのために、この例は三番目の項目をもとにしていますが、読みやすくするために Web Workers を使わないようにしています。(あと、正直に言うと、書きやすくするためでもあるんですけどね)。

**警告:** この例は特に技術的なレビューが必要です。
```

/*
* Starting with the semicolon is in case whatever line of code above this example
* relied on automatic semicolon insertion (ASI). The browser could accidentally
* think this whole example continues from the previous line. The leading semicolon
* marks the beginning of our new line if the previous one was not empty or terminated.
*
* Let us also assume that MyGame is previously defined.
*
* MyGame.lastRender keeps track of the last provided requestAnimationFrame timestamp.
* MyGame.lastTick keeps track of the last update time. Always increments by tickLength.
* MyGame.tickLength is how frequently the game state updates. It is 20 Hz (50ms) here.
*
* timeSinceTick is the time between requestAnimationFrame callback and last update.
* numTicks is how many updates should have happened between these two rendered frames.
*
* render() is passed tFrame because it is assumed that the render method will calculate
*          how long it has been since the most recently passed update tick for
*          extrapolation (purely cosmetic for fast devices). It draws the scene.
*
* update() calculates the game state as of a given point in time. It should always
*          increment by tickLength. It is the authority for game state. It is passed
*          the DOMHighResTimeStamp for the time it represents (which, again, is always
*          last update + MyGame.tickLength unless a pause feature is added, etc.)
*
* setInitialState() Performs whatever tasks are leftover before the mainloop must run.
*                   It is just a generic example function that you might have added.
*/

;(function () {
  function main( tFrame ) {
    MyGame.stopMain = window.requestAnimationFrame( main );
    var nextTick = MyGame.lastTick + MyGame.tickLength;
    var numTicks = 0;

    //If tFrame < nextTick then 0 ticks need to be updated (0 is default for numTicks).
    //If tFrame = nextTick then 1 tick needs to be updated (and so forth).
    //Note: As we mention in summary, you should keep track of how large numTicks is.
    //If it is large, then either your game was asleep, or the machine cannot keep up.
    if (tFrame > nextTick) {
      var timeSinceTick = tFrame - MyGame.lastTick;
      numTicks = Math.floor( timeSinceTick / MyGame.tickLength );
    }

    queueUpdates( numTicks );
    render( tFrame );
    MyGame.lastRender = tFrame;
  }

  function queueUpdates( numTicks ) {
    for(var i=0; i < numTicks; i++) {
      MyGame.lastTick = MyGame.lastTick + MyGame.tickLength; //Now lastTick is this tick.
      update( MyGame.lastTick );
    }
  }

  MyGame.lastTick = performance.now();
  MyGame.lastRender = MyGame.lastTick; //Pretend the first draw was on first update.
  MyGame.tickLength = 50; //This sets your simulation to run at 20Hz (50ms)

  setInitialState();
  main(performance.now()); // Start the cycle
})();
```

他のやり方としては、単に特定のものをより少ない頻度でやることです。もしあなたのアップデートループの一部の処理が重く時間に制約がないのであれば、その頻度を下げることと、理想的に言うと、より長い時間を単位としたかたまりへとひきのばすべきです。これが暗に使われている例は The Artillery Blog for Artillery Games でみることができます。そこで彼らはガベージコレクションの最適化のためにガベージジェネレーションのランクを調整しています 。明らかにリソースのクリーンアップは時間に制約がありません (とりわけ整理整頓をすることがゴミそれ自体よりも混乱を招くようなときは特にです)。

これはまたあなた自身のタスクにも適用できるかもしれません。それらは利用可能なリソースが問題になった時によき抑制をしてくれます。

まとめ
---

ちゃんと言っておきたいのですが、上に書いたようなことのどれもが - もしくはどれも全然かもしれませんが - あなたのゲームに最高に作用するとは限りません。正確な決断とはあなたが作りたい (もしくは作りたくない) ものとのトレードオフにもっぱら依存しています。心配事は主に別の選択肢へと舵を切ることです。幸運なことに、これに関して私は全然経験がありませんが、これは猛烈なモグラたたきのようなものだと聞いています。

ウェブのような管理されたプラットフォームで覚えておいてほしいことはあなたのループはひょっとしたらある特定の期間で止まるかもしれないということです。これはユーザーがあなたのタブを選択から外してブラウザーが自身の `requestAnimationFrame` コールバックを Sleep (もしくは slow) する時に起こります。この状況に対応する方法はたくさんありますし、シングルプレーヤーかマルチプレーヤーによって違います。いくつかの方法としては

* 途切れを「ポーズ」として考え、時間をとばす。
    + ほとんどのマルチプレーヤーゲームでは問題だと思うかもしれませんが。
* 途切れに追いつくようシミュレートする。
    + 長い間落ちている、もしくは/かつ、複雑なアップデートがあると問題です。
* ゲームの状態を Peer もしくはサーバーから回復させる。
    + これがダメな場合とは、これもあなたの Peer もしくはサーバーが out-of-date になった場合と、もしくは、シングルプレーヤーのゲームでサーバーが無かった時にそれらが存在しなかった場合です。

ひとたびメインループが作られてあなたが一連の仮説とゲームに適したトレードオフに基づいて決断したのなら、あなたの決断力を物理とか、AI とか、サウンドとか、ネットワーク同期とかそのほか何でもあなたのゲームが求めるものへと使う段階にやってきました。


HTML5 ゲーム開発入門 - ゲーム開発

HTML5 ゲーム開発入門
=============

長所
--

1. HTML5 で作られたゲームはスマートフォン、タブレット、PC、スマート TV で動作します。
2. 他のメディアと同様に、ウェブ全体でゲームを広告、宣伝することができます。
3. 支払い。好きな支払い処理サービスを使って課金できます。
4. 好きな時にゲームを更新できます。
5. 自身のアナリティクスを集められます。
6. 顧客ともっと身近に繋がれます。
7. プレイヤーはいつでもどこでもゲームをプレイできます。
ウェブ技術
-----

| **機能** | **技術** |
| --- | --- |
| **オーディオ** | ウェブオーディオ API |
| **グラフィック** | WebGL (OpenGL ES
 2.0)
  |
| **入力** | タッチイベント、
 Gamepad API、端末センサー、WebRTC、全画面 API、ポインターロック API |
| **言語** | JavaScript (Emscripten を使って C/C++ を JavaScript にコンパイルする) |
| **ネットワーク** | WebRTC や WebSockets |
| **ストレージ** | IndexedDB や「クラウド」 |
| **ウェブ** | HTML,
 CSS,
 SVG,
 ソーシャル API (およびその他いろいろ！)
  |

全画面 API

全画面のゲームプレイに使います。

Gamepad API

ゲームパッドやゲームコントローラーを使用します。

HTML および CSS

ゲームのユーザーインターフェイスを構築し、装飾し、レイアウトします。

HTML audio

簡単な効果音や音楽を簡単に再生することができます。

IndexedDB

ユーザーデータを自分のコンピューターや 端末に保存します。

JavaScript

 ゲームのコードを書くための高速ウェブプログラミング言語です。
 簡単に既存のゲームを移植するには、 Emscripten や Asm.js を使用します。

ポインターロック API

マウスなどのポインティングデバイスをゲームのインターフェイス内にロックします。

SVG (Scalable Vector Graphics)

ユーザーの画面の大きさや解像度に関わらず、滑らかに拡大縮小できるベクターグラフィックを構築することができます。

型付き配列

JavaScript から生のバイナリーデータにアクセスし、GLテクスチャやゲームデータなど、あらゆるものを操作することができます。

ウェブオーディオ API

オーディオの再生、合成、操作をリアルタイムに制御します。

WebGL

高性能でハードウェアアクセラレーションに優れた三次元（および二次元）グラフィックを作成することができます。OpenGL ES 2.0。

WebRTC

電話会議やチャットのように 2 人のユーザー間で他のアプリケーションのデータをやり取りするなど、音声や映像データを制御するリアルタイム通信です。

WebSockets

アプリやサイトをサーバーに接続し、データをリアルタイムに送受信します。マルチプレイヤーゲームアクションやチャットサービスなどに最適です。

Web Workers

マルチコアプロセッサーのために、独自の JavaScript コードを実行するバックグラウンドスレッドを生成します。

XMLHttpRequest および ファイル API

新しいゲームレベルやアートワークのダウンロード、非リアルタイムのゲームステータス情報の送信など、ウェブサーバーから必要なあらゆるデータを送受信することができます。


純粋な JavaScript を使ったブロック崩しゲーム - ゲーム開発

純粋な JavaScript を使ったブロック崩しゲーム
============================

* 次のページ »

このステップバイステップのチュートリアルでは、すべて JavaScript だけで書かれた、 HTML5 の `<canvas>` で表示できる簡単な **MDN ブロック崩し**ゲームを作ります。

各ステップには編集可能なライブサンプルがあるので、中間ステージがどのように見えるかを確認しながらプレイすることができます。画像のレンダリングと移動、衝突検出、制御機構、勝敗状態などの基本的なゲーム メカニックを使用するための `<canvas>` 要素の基本的な使用方法を学びます。

このシリーズのほとんどの記事は理解するために初歩または中級レベルの JavaScript の知識を必要とします。このチュートリアルを一通りこなすことで簡単なウェブゲームを作れるようになるでしょう。

![パドルを使用してボールを弾き、スコアとライフをキープしながらレンガのフィールドを破壊していくゲーム「MDN Breakout」のゲーム画面。](/ja/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript/mdn-breakout-gameplay.png)

レッスン詳細
------

全てのレッスンは以下の通りです。そしてこれから一緒に作る MDN ブロック崩しゲームの各バージョンは GitHub 上で入手可能です。

1. キャンバスを作ってその上に描画する
2. ボールを動かす
3. ボールを壁で反射させる
4. パドルとキーボード操作
5. ゲームオーバー
6. ブロックのかたまりを作る
7. 衝突検出
8. スコアと勝ち負けを記録する
9. マウス操作
10. 仕上げ

まずは JavaScript だけで始めるのがウェブゲーム開発の確実な知識を手に入れる一番良い方法です。そのあと、自分のプロジェクトで使うフレームワークを選びましょう。フレームワークは JavaScript 言語で書かれた単なるツールです。ですから、たとえフレームワークを用いて開発しようとしていてもまずはその言語を学び、手元で実際に何が起こっているか理解すると良いでしょう。フレームワークは開発速度を上げ、ゲームのとるに足らない部分を処理してくれますが、もし何かが思ったように動かないなんてことがあったらいつでもデバッグしたり、あるいは単に JavaScript で自分なりの解を出すということもできるのです。

**メモ:** ゲームライブラリを用いた 2D ウェブゲーム開発に興味があるのであれば、このシリーズに対応する Phaser を使ったブロック崩しゲームも参照してください。

**メモ:** このシリーズはゲーム開発ワークショップのハンズオンの資料として使えます。ゲーム開発全般について話すつもりならこのチュートリアルに基づいた Gamedev Canvas Content Kit も利用できます。

次のステップ
------

それでは始めましょう! 最初の章、 キャンバスを作ってその上に描画するに進みます。

* 次のページ »


Phaser を使用した 2D ブロック崩しゲーム - ゲーム開発

Phaser を使用した 2D ブロック崩しゲーム
=========================

* 次のページ » (en-US)

このステップバイステップのチュートリアルでは、シンプルなモバイル **MDN ブロック崩し**ゲーム を、 JavaScript で書き、 Phaser フレームワークを使用して作成します。

各ステップには、編集可能なライブサンプルがあるので、中間ステージがどのように見えるかを確認しながら遊ぶことができます。 Phaser フレームワークを使用して、画像のレンダリングと移動、衝突の検出、コントロールメカニズム、フレームワーク固有のヘルパー関数、アニメーションと調整、勝利と敗北状態などの基本的なゲームメカニズムを使用するための基本を学びます。

この連載記事を最大限に活用するためには、すでに基礎から中級の JavaScript の知識を持っている必要があります。このチュートリアルを動作させた後は、 Phaser を使って自身の簡単なウェブゲームを作ることができるはずです。

![Phaser で作成したゲーム MDN ブロック崩しのゲーム画面。パドルを使用してボールを跳ね返し、ポイントとライフを維持しながら、レンガのフィールドを破壊することができます。](/ja/docs/Games/Tutorials/2D_breakout_game_Phaser/mdn-breakout-phaser.png)

学習内容
----

すべてのレッスン、そして私たちが一緒に作っている MDN ブロック崩しゲームのさまざまなバージョンは、 GitHub で利用可能です。

1. フレームワークの初期化 (en-US)
2. 拡大縮小 (en-US)
3. 資産を読み込んで画面の内側へ表示する (en-US)
4. ボールを移動させる (en-US)
5. 物理演算
6. 壁で跳ね返す (en-US)
7. プレイヤーパドルと操作 (en-US)
8. ゲームオーバー (en-US)
9. レンガ場を作る (en-US)
10. 衝突判定 (en-US)
11. 得点 (en-US)
12. ゲームの勝利 (en-US)
13. ライフの追加 (en-US)
14. アニメーションと調整 (en-US)
15. ボタン (en-US)
16. ゲームプレイのランダム化 (en-US)

学習経路に関する注意点として、純粋な JavaScript から始めることが、ウェブゲーム開発の確かな知識を得るための最良の方法です。もしあなたが純粋な JavaScript のゲーム開発にまだ慣れていないなら、先にこのシリーズの対になるものである純粋な JavaScript を使用した 2D ブレイクアウトゲームをやっておくことをお勧めします。

その後、好きなフレームワークを選んで、プロジェクトに使用することができます。私たちは、良いサポートとコミュニティが利用でき、プラグインの良いセットがある、堅実なフレームワークである Phaser を選びました。フレームワークは、開発時間を短縮し、退屈な部分を引き受けてくれるので、あなたは楽しいことに集中することができます。しかし、フレームワークは常に完璧というわけではありません。予期せぬことが起こったり、フレームワークが提供しない機能を書きたい場合、純粋な JavaScript の知識が必要になります。

**メモ:** この連載記事は、ゲーム開発の体験型ワークショップの素材として使用することができます。また、Phaser を使ったゲーム開発についての講演を行う場合、このチュートリアルを元にした Gamedev Phaser Content Kit を使用することができます。

次のステップ
------

では、始めましょう。シリーズの最初の部分 - フレームワークの初期化 (en-US)に向かいましょう。

* 次のページ » (en-US)


物理演算 - ゲーム開発

物理演算
====

* « 前のページ (en-US)
* 次のページ » (en-US)

これは、Gamedev Phaser チュートリアルの 16 ステップ中、 **5 ステップ目**になります。このレッスンを終えた後のソースコードは Gamedev-Phaser-Content-Kit/demos/lesson05.html で見ることができます。

モノ同士の衝突を正しく処理するためには、物理演算が必要になります。この文書では、 Phaser での実装と、典型的な例を紹介します。

物理演算の追加
-------

Phaser は Arcade Physics、P2、そして Ninja Physics と、3 つの異なる物理演算エンジンを備えています。また商用プラグインとして Box2D も物理演算エンジンとして利用できます。チュートリアルで作成しているような単純なゲームでは、複雑な幾何計算を必要としません。そのような場合には Arcade Physics を利用すると良いでしょう。

まず最初に、ゲーム内の Arcade Physics エンジンを初期化しましょう。以下のように、`create` 関数の最初に `physics.startSystem()` メソッドを追加します（関数内の最初の行にします）。

```js
game.physics.startSystem(Phaser.Physics.ARCADE);
```

標準では Phaser オブジェクトは物理演算エンジンを利用しません。そのため、`create()` の末尾に次の行を追加して、ボールから物理演算エンジンを利用できるようにします：

```js
game.physics.enable(ball, Phaser.Physics.ARCADE);
```

次にボールを動かします。次のように、`create()` 末尾で body 属性の持つ `velocity` 属性を設定します。

```js
ball.body.velocity.set(150, 150);
```

以前作成した、更新処理の削除
--------------

`update()` 関数から `x` と `y` に値を追加する古いメソッドを削除することを忘れないでください。

```js
function update() {
  ball.x += 1;
  ball.y += 1;
}
```

以上で、物理演算エンジンを組み込むことができました。

最終的に作成されたコード
------------

最終的に得られたコードは以下の通りです。

```js
let ball;

function preload() {
  game.scale.scaleMode = Phaser.ScaleManager.SHOW\_ALL;
  game.scale.pageAlignHorizontally = true;
  game.scale.pageAlignVertically = true;
  game.stage.backgroundColor = "#eee";
  game.load.image("ball", "img/ball.png");
}

function create() {
  game.physics.startSystem(Phaser.Physics.ARCADE);
  ball = game.add.sprite(50, 50, "ball");
  game.physics.enable(ball, Phaser.Physics.ARCADE);
  ball.body.velocity.set(150, 150);
}

function update() {}
```

`index.html` を再読み込みすると、ボールは 1 方向に進み続けます。現在、物理エンジンには重力加速度も摩擦係数も設定されていません。重力加速度を設定すれば、ボールは落下するようになります。また、摩擦係数を設定すれば、ボールが摩擦で停止するようになります。

物理学を楽しむ
-------

今回扱った内容以外にもできることはたくさんあります。例えば、 `ball.body.gravity.y = 100;` と追加することで、ボールに影響する重力を設定できます。その結果として、ボールが重力に引かれて、落下するようになります。

このような機能はほんの一部分です。公式の physics documentation には、物理演算に関する数多くの関数と変数が、 Arcade と P2 物理演算エンジンの使用例とともに解説されています。

自分のコードと比較しよう
------------

上記のコードや、下記のデモと比較して、どのように動作しているかを理解しましょう。

次のステップ
------

次のステップでは、壁でボールを跳ね返す (en-US)を実装します。

* « 前のページ (en-US)
* 次のページ » (en-US)


仕上げ - ゲーム開発

仕上げ
===

* « 前のページ

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **10 ステップ目、最後のステップ**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson10.htmlで見ることができます。

私たちが書くゲームには、常に改良の余地があります。例えば、プレイヤーに複数の人生を提供することができます。 1 人または 2 人がミスをしても、ゲームを完了させることができるのです。また、コードのレンダリングを改善することもできます。

プレイヤーにライフを与える
-------------

ライフを実装するのは極めて単純です。まずは他の変数を宣言したところと同じところにライフの数を保存する変数を追加しましょう。

```js
let lives = 3;
```

ライフカウンタを描画するのはスコアカウンタを描画するのとほとんど同じです。次の関数を自分のコードの `drawScore()` の下に追加してください。

```js
function drawLives() {
  ctx.font = "16px Arial";
  ctx.fillStyle = "#0095DD";
  ctx.fillText(`Lives: ${lives}`, canvas.width - 65, 20);
}
```

すぐにゲームを終了するのではなく、ライフがなくなるまでライフを減らしていきます。また、プレイヤーが次のライフで始めるときに、ボールとパドルの位置をリセットすることができます。そこで、 `draw()` 関数の中で、以下の 3 行を置き換えてください。

```js
alert("GAME OVER");
document.location.reload();
clearInterval(interval); // クロームがゲームを終了するのに必要
```

これに以下で示すようなもう少し複雑なロジックを追加します。

```js
lives--;
if (!lives) {
  alert("GAME OVER");
  document.location.reload();
  clearInterval(interval); // クロームがゲームを終了するのに必要
} else {
  x = canvas.width / 2;
  y = canvas.height - 30;
  dx = 2;
  dy = -2;
  paddleX = (canvas.width - paddleWidth) / 2;
}
```

ボールが画面下端に当たったときに `lives` 変数からライフを 1 つ引きます。もしライフが残っていなかったらゲームは負けです。ライフが残っている場合は、ボールの位置とパドルの位置がリセットされ、ボールの動きもリセットされます。

### ライフ表示を描画する

`drawLives()` への呼び出しを`draw()` 関数内に追加する必要があります。 `drawScore()` の呼び出しの下に追記してください。

```js
drawLives();
```

requestAnimationFrame()で描画を改善する
-------------------------------

ではゲーム機構に直結しない部分、描画に関わる部分にとりかかりましょう。 `requestAnimationFrame` は今は `setInterval()` で実装している固定フレームレートよりもより良くブラウザーがゲームを描画できるようにします。

```js
const interval = setInterval(draw, 10);
```

これを簡単に次の行で置き換えます。

```js
draw();
```

そして、それぞれのインスタンスを削除します。

```js
clearInterval(interval); // クロームがゲームを終了するのに必要
```

次に、 `draw()` 関数の一番下（中括弧を閉じる直前）に、以下の行を追加します。これは、 `draw()` 関数が何度も繰り返し呼び出されるようにするためのものです。

```js
requestAnimationFrame(draw);
```

これで`draw()`関数が`requestAnimationFrame()`ループの中で何度も実行されるようになりましたが、固定の10ミリ秒のフレームレートではなくブラウザーに制御を託しています。ブラウザーはフレームレートを適切に同期し図形を必要なときだけ描画します。これは古い`setInterval()`メソッドよりも効率的で滑らかなアニメーションループを生み出します。

自分のコードを比べる
----------

これで全部です。ゲームの最終版が準備でき、プレイできる状態になりました。

**メモ:** ライフの数とパドルでボールが跳ねる角度を替えてみましょう。

ゲームクリア - 今のところは
---------------

おめでとうございます。これで全てのレッスンを終えました。ここまでで、キャンバス操作の基本をと簡単な 2D ゲームの裏にあるロジックを学んだはずです。フレームワークを学びゲーム開発を続ける良い時期です。このシリーズに対応する Phaser を使ったブロックくずしゲームやデバイス回転方向を使った 2D 迷路ゲーム (en-US)チュートリアルを見てみると良いでしょう。 MDN のゲームセクションで発想やより多くの知識を探してみても良いでしょう。

また、このチュートリアルシリーズの目次を見返せます。コーディングを楽しみましょう。

* « 前のページ


ゲームオーバー - ゲーム開発

ゲームオーバー
=======

* « 前のページ
* 次のページ »

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **5 ステップ目**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson5.htmlで見ることができます。

ボールが壁に当たって跳ねているのを見たり、パドルを移動させたりできるのは楽しいのですが、それ以外は何もせず、ゲームの進行や最終目標がありません。ゲームプレイの観点からは、負けることがあってもいいのではないでしょうか。ブロック崩しで負ける理屈は簡単です。パドルでボールを飛ばして画面の下端へ到達させたらゲームオーバーです。

ゲームオーバーを実装する
------------

自分のゲームにゲームオーバーを実装してみましょう。第 3 章ではボールを壁で跳ね返るようにしました。以下はその引用です。

```js
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
  dx = -dx;
}

if (y + dy > canvas.height - ballRadius || y + dy < ballRadius) {
  dy = -dy;
}
```

4 辺全てでボールを弾ませるのではなく、 3 辺、すなわち上端と左右のみで跳ね返るようにしましょう。底を打ったときゲームは終わりになります。 2 番目の if 節を編集して、ボールがキャンバスの下端で衝突したときにゲームオーバー状態が発動する if else 節にしましょう。ここでは簡単に、アラートメッセージを表示して、ページの再読み込みによりゲームを再開するだけにしましょう。

まず、 `setInterval()` を最初に呼び出しているところを置き換えます。

```js
setInterval(draw, 10);
```

置き換えるとこうなります。

```js
const interval = setInterval(draw, 10);
```

次に 2 番目の if 節を次の内容で置き換えましょう。

```js
if (y + dy < ballRadius) {
  dy = -dy;
} else if (y + dy > canvas.height - ballRadius) {
  alert("GAME OVER");
  document.location.reload();
  clearInterval(interval); // Needed for Chrome to end game
}
```

パドルをボールに当てる
-----------

このレッスンの最後に、ボールとパドルの間に何らかの衝突判定を作成し、ボールがパドルで跳ねてプレイエリアに戻れるようにします。最も簡単なのは、ボールの中心がパドルの左端と右端の間にあるかどうかをチェックすることです。最後に修正したコードを再び以下のように更新してください。

```js
if (y + dy < ballRadius) {
  dy = -dy;
} else if (y + dy > canvas.height - ballRadius) {
  if (x > paddleX && x < paddleX + paddleWidth) {
    dy = -dy;
  } else {
    alert("GAME OVER");
    document.location.reload();
    clearInterval(interval);
  }
}
```

ボールがキャンバスの下端に当たっていたら、パドルにも当たっているかどうか確認します。もしパドルに当たっていたら、思ったとおりにボールは弾みます。当たらなかったら、先ほどと同じようにゲームオーバーになります。

自分のコードと比べる
----------

自分のコードと比べられるように、実際に動くコードを以下に示します。

**メモ:** ボールがパドルに当たったときに速く動くようにしましょう。

次のステップ
------

今のところかなり順調に進歩してきていて、ゲームも負けるようになったことでもっと遊ぶ価値が感じられるようになってきました。第 6 章のブロックのかたまりを作るに進み、ボールが壊せるブロックを作りましょう。

* « 前のページ
* 次のページ »


衝突検出 - ゲーム開発

衝突検出
====

* « 前のページ
* 次のページ »

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **7 ステップ目**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson7.htmlで見ることができます。

ブロックはすでに画面の内側へ現れていますが、ボールがその中を通過していくので、ゲームはまだそれほど面白くはありません。レンガを跳ね返して壊せるように、衝突判定を追加することを考えなければなりません。

もちろん、これをどのように実装するかは自由ですが、ボールが矩形に触れているかどうかを計算するのは大変です。なぜなら、キャンバスにはこのためのヘルパー関数がないからです。このチュートリアルでは、可能な限り簡単な方法で実装することにします。ボールの中心が与えられたレンガのどれかに衝突しているかどうかをチェックします。これは毎回完璧な結果を得られるわけではありませんし、衝突検出を行うにはもっと洗練された方法がありますが、基本的な概念を学ぶにはこの著作物で十分です。

衝突検出関数
------

最初の第一歩として、毎フレーム描画されるたびに全てのブロックを通してループし、ひとつひとつのブロックの位置をボールの座標と比較する衝突検出関数を作成しましょう。コードがより読みやすくなるように、衝突検出のループの中でブロックオブジェクトを保存する変数 `b` を定義します。

```js
function collisionDetection() {
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      const b = bricks[c][r];
      // 計算
    }
  }
}
```

もしボールの中央がブロックの 1 つの座標の内部だったらボールの向きを変えます。ボールの中央がブロックの内部にあるためには次の 4 つの命題が全て真でなければなりません。

* ボールの x 座標がブロックの x 座標より大きい
* ボールの x 座標がブロックの x 座標とその幅の和より小さい
* ボールの y 座標がブロックの y 座標より大きい
* ボールの y 座標がブロックの y 座標とその高さの和より小さい

コードに書き下ろしてみましょう。

```js
function collisionDetection() {
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      const b = bricks[c][r];
      if (x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {
        dy = -dy;
      }
    }
  }
}
```

上記のブロックを自分のコードの `keyUpHandler()` 関数の下に追加してください。

ブロックが当たった後に消えるようにする
-------------------

上記のコードは期待したとおり動作し、ボールの向きを変えるはずです。問題はブロックがそのままとどまっているということです。ボールに既に当たったブロックを取り除く方法を考え出さなければなりません。これはそれぞれのブロックを画面上に描画したいかどうかを示す新たなパラメーターを追加することで達成できます。ブロックを初期化している部分のコードで、それぞれのブロックオブジェクトに `status` プロパティを追加しましょう。次の部分のコードをハイライトした行で示したように更新してください。

```js
const bricks = [];
for (let c = 0; c < brickColumnCount; c++) {
  bricks[c] = [];
  for (let r = 0; r < brickRowCount; r++) {
    bricks[c][r] = { x: 0, y: 0, status: 1 };
  }
}
```

次に、それぞれのブロックを描画する前に `status` プロパティの値を `drawBricks()` 関数で確認します。もし `status` が `1` なら描画します。でももし `0` ならそのブロックは既にボールに当たっていますから、これ以上画面上に描画されてほしくありません。自分の `drawBricks()` 関数を次のように更新してください。

```js
function drawBricks() {
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      if (bricks[c][r].status === 1) {
        const brickX = c \* (brickWidth + brickPadding) + brickOffsetLeft;
        const brickY = r \* (brickHeight + brickPadding) + brickOffsetTop;
        bricks[c][r].x = brickX;
        bricks[c][r].y = brickY;
        ctx.beginPath();
        ctx.rect(brickX, brickY, brickWidth, brickHeight);
        ctx.fillStyle = "#0095DD";
        ctx.fill();
        ctx.closePath();
      }
    }
  }
}
```

衝突検出関数で状態を追跡、更新する
-----------------

ここでは `collisionDetection()` 関数内で `status` プロパティをブロックに紐づけていきます。もしブロックがアクティブ (状態が `1`) なら衝突が起きるかどうか確認します。もし衝突が起きるのなら、画面上に描画されないようにそのブロックの状態を `0` に設定します。自分の `collisionDetection()` 関数を以下に示すように更新してください。

```js
function collisionDetection() {
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      const b = bricks[c][r];
      if (b.status === 1) {
        if (
          x > b.x &&
          x < b.x + brickWidth &&
          y > b.y &&
          y < b.y + brickHeight
        ) {
          dy = -dy;
          b.status = 0;
        }
      }
    }
  }
}
```

衝突検出を有効にする
----------

`collisionDetection()` 関数への呼び出しをメインの `draw()` 関数に追加して仕上げとします。次の行を `draw()` 関数の、 `drawPaddle()` の呼び出しのすぐ下に追加してください。

```js
collisionDetection();
```

コードを比べる
-------

これでボールの衝突検出がそれぞれのブロックに対してフレームごとに確認されるようになりました。ブロックを壊せるようになったのです。

**メモ:** ボールの色をブロックに当たったときに変えましょう。

次のステップ
------

着実にゴールに近づいています。では、先に進みましょう。第 8 章ではどのようにスコアと勝ち負けを記録するかを見てみます。

* « 前のページ
* 次のページ »


マウス操作 - ゲーム開発

マウス操作
=====

* « 前のページ
* 次のページ »

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **9 ステップ目**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson9.htmlで見ることができます。

ゲーム自体は実際に完成したので、磨き上げにかかりましょう。既にキーボード操作を追加していますが、マウス操作も簡単に追加できます。

マウスの動作を監視する
-----------

マウスの操作を監視するのはキー入力を監視するのよりも簡単です。 `mousemove` イベントのリスナーさえあればよいのです。次の行を、他のイベントリスナーの近く、 `keyup event` のすぐ下に追記してください。

```js
document.addEventListener("mousemove", mouseMoveHandler, false);
```

パドルの動きをマウスの動きと紐付ける
------------------

ポインターの座標に基づいてパドルの位置を更新することができます。以下のハンドラー関数がまさにそれを行うものです。以下の関数を、前に追加した行の下に、あなたのコードに追加してください。

```js
function mouseMoveHandler(e) {
  const relativeX = e.clientX - canvas.offsetLeft;
  if (relativeX > 0 && relativeX < canvas.width) {
    paddleX = relativeX - paddleWidth / 2;
  }
}
```

この値は、ビューポート内のマウスの水平位置 (`e.clientX`) からキャンバスの左端とビューポートの左端間の距離 (`canvas.offsetLeft`) を引いたもので、実質的にこれはキャンバス左端からマウスポインターまでの距離と等しくなっています。ポインタの相対 X 位置が 0 より大きく、キャンバスの幅よりも小さい場合、ポインタはキャンバスの境界内にあり、`paddleX` 位置（パドルの左端に固定）は `relativeX` 値からパドルの幅の半分を引いた値に設定され、実際の移動はパドルの中央に対して相対的に行われることになります。

パドルはマウスカーソルの位置を追うようになりますが、動きをキャンバスの大きさに制限しているため、両端で消え失せてしまうようなことはありません。

自分のコードと比べる
----------

比較用にコードの最新の状態を示します。

**メモ:** パドル動作の境界を調節して、Canvasの両端でもパドルの半分ではなく全体が見えるようにしてください。

次のステップ
------

最後に微調整する準備が整った、完全なゲームが完成しました。では、仕上げに入りましょう。

* « 前のページ
* 次のページ »


スコアと勝ち負けを記録する - ゲーム開発

スコアと勝ち負けを記録する
=============

* « 前のページ
* 次のページ »

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **8 ステップ目**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson8.htmlで見ることができます。

レンガを破壊するのはとてもクールですが、ユーザーがレンガにぶつかるごとにこの点を与え、その合計点をカウントしていくことで、さらに素晴らしいゲームになります。

スコアを数える
-------

ゲーム中に自分のスコアを見ることができれば、最終的には友達を感動させることができます。スコアを記録するための変数が必要です。 JavaScript に以下のように、残りの変数の後に追加してください。

```js
let score = 0;
```

スコア表示を作成し更新するために `drawScore()` 関数も必要です。次のコードを `collisionDetection()` 関数のあとに追加してください。

```js
function drawScore() {
  ctx.font = "16px Arial";
  ctx.fillStyle = "#0095DD";
  ctx.fillText(`Score: ${score}`, 8, 20);
}
```

文字をキャンバス上に描画するのは図形を描画するのと似ています。フォント定義は CSS 出するものとちょうど同じように描きます。大きさとフォントの種類は `font()` メソッドで設定できます。それからフォントの色を設定するには `fillStyle()` を、キャンバス上に配置される実際の文章を設定するには `fillText()` を使用してください。最初の引数は文章自体です。上記のコードは現在のポイントの数を表示します。最後の 2 つの引数は文章がキャンバス上に置かれる座標です。

ブロックに当たるたびにスコアを与えるには、衝突が検出されるたびにスコア変数を増加させる1行を `collisionDetection()` 関数に追加します。次のハイライトされた行を自分のコードに追加してください。

```js
function collisionDetection() {
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      const b = bricks[c][r];
      if (b.status === 1) {
        if (
          x > b.x &&
          x < b.x + brickWidth &&
          y > b.y &&
          y < b.y + brickHeight
        ) {
          dy = -dy;
          b.status = 0;
          score++;
        }
      }
    }
  }
}
```

`drawScore()` を `draw()` 関数から呼び続けることで新しいフレームごとにスコアは最新の状態に保たれます。次の行を `draw()` の中、ちょうど `drawPaddle()` の呼び出しの下に追加してください。

```js
drawScore();
```

全てのブロックが崩されたときに勝利を伝えるメッセージを表示する
-------------------------------

ポイントを集め続けるという動作はうまく働きますが、永久に増やし続けることは出来ません。全てのブロックが崩されたらどうなるのでしょうか。何においてもそれこそがゲームの主目標なのですから、得られる全てのポイントが集まったときには勝利を伝えるメッセージを表示すべきです。次のハイライトされた部分を自分の `collisionDetection()` 関数に追記してください。

```js
function collisionDetection() {
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      const b = bricks[c][r];
      if (b.status === 1) {
        if (
          x > b.x &&
          x < b.x + brickWidth &&
          y > b.y &&
          y < b.y + brickHeight
        ) {
          dy = -dy;
          b.status = 0;
          score++;
          if (score === brickRowCount \* brickColumnCount) {
            alert("YOU WIN, CONGRATULATIONS!");
            document.location.reload();
            clearInterval(interval); // Needed for Chrome to end game
          }
        }
      }
    }
  }
}
```

これのおかげで、全てのブロックが崩されたときにユーザーは実際にゲームに勝つことができます。ゲームにおいてはこれは非常に重要です。アラートのボタンがクリックされたら `document.location.reload()` 関数はページを再読込しゲームをもう一度始めます。

自分のコードと比べる
----------

自分のものと比べたいときのために最新のコードをいかに示します。このように見え、そして動くはずです。

**メモ:** ブロックに当たるたびにより多くのポイントを追加し、ゲームの終わりに集めたポイントの数を表示するようにしましょう。

次のステップ
------

この時点でもこのゲームはかなりよく見えます。次のレッスンではマウス操作を追加することでゲームの魅力を広げます。

* « 前のページ
* 次のページ »


ボールを壁で跳ね返させる - ゲーム開発

ボールを壁で跳ね返させる
============

* « 前のページ
* 次のページ »

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **3 ステップ目**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson3.htmlで見ることができます。

ボールが移動するのを見るのは楽しいですが、すばやく画面の内側へ消えてしまうので、ボールの楽しみが半減してしまいます。この問題を解決するために、とても簡単な衝突判定（詳しくは後ほど説明します）を実装して、ボールをキャンバスの 4 つの辺で跳ね返らせるようにしましょう。

簡単な衝突検出
-------

衝突を検出するために、ボールが壁に触れているか（衝突しているか）どうかをチェックし、触れていればそれに応じてボールの移動方向を変更します。

計算を簡単にするために、描画された円の半径を保持し、計算に使用する `ballRadius` という変数を定義しましょう。これをコードに追加してください。既存の変数宣言の下のどこかです。

```js
const ballRadius = 10;
```

あわせて `drawBall()` 関数内のボールを描画している行も次のように更新しましょう。

```js
ctx.arc(x, y, ballRadius, 0, Math.PI \* 2);
```

### 上端と下端で跳ね返させる

ボールを跳ね返させる壁は 4 つあります。まずは上端に注目しましょう。毎フレーム、ボールがキャンバスの上端に触っているかどうか確認する必要があります。もし触っているなら、ボールの動きを反転させ、ボールが反対方向に動き、視界の範囲内に留まるようにしましす。座標系は左上端から始まることを思い出しながら考えてみれば、次のようなコードが思いつくでしょう。

```js
if (y + dy < 0) {
  dy = -dy;
}
```

もしボールの位置の `y` の値が 0 未満だったら、符号反転させた値を設定することで y 軸方向の動きの向きを変えます。もしボールが上に向かって毎フレーム 2 ピクセルの速さで動いていたら、今度は「上」に向かって毎フレーム -2 ピクセルの速さで動く、つまり下に向かって毎フレーム 2 ピクセルの速さで動きます。

上記のコードは上端でボールを弾ませていました。では今度は下端について考えてみましょう。

```js
if (y + dy > canvas.height) {
  dy = -dy;
}
```

`y` 座標がキャンバスの高さより高かったら（左上端から `y` の値を数えているため、上端は 0 で始まり下端はキャンバスの高さである 480 ピクセルとなることを思い出してください）、先程のように `y` 軸方向の動きを反転させます。

これら 2 つの文を合わせればコードの冗長さを減らせます。

```js
if (y + dy > canvas.height || y + dy < 0) {
  dy = -dy;
}
```

2 つの文のどちらかが `true` だったら、ボールの動きを反転させます。

### 左端と右端で跳ね返させる

上端と下端を対処したところで、左端と右端を考えてみましょう。実のところとても良く似ていて、 `y` を `x` で置き換えて文を繰り返すだけでよいのです。

```js
if (x + dx > canvas.width || x + dx < 0) {
  dx = -dx;
}

if (y + dy > canvas.height || y + dy < 0) {
  dy = -dy;
}
```

ここで上記のコードを draw() 関数の、ちょうど閉じ波括弧の前に挿入しておいてください。

### まだボールが壁に隠れる!

ここでコードを試してみましょう。驚くはずです。 Canvas の四辺全てでボールが跳ね返っています。でも別の問題がありました。ボールが壁にぶつかるとき、位置を変える少し前に壁に沈んでしまいます。

![](/ja/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls/ball-in-wall.png)

壁と円周の衝突地点を計算すべきところで、壁と円の中心の衝突地点を計算しているのがこの理由です。ボールは壁に触ったときに跳ね返る、壁に半分のめり込んだときに跳ね返っても仕方ありません。そこで円周を含めるために文を少し調節します。最後に追加したコードを次のように書き換えます。

```js
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
  dx = -dx;
}
if (y + dy > canvas.height - ballRadius || y + dy < ballRadius) {
  dy = -dy;
}
```

ボールの中心と辺の距離がボールの半径とちょうど等しくなったときに動く向きを変えます。半径を辺の長さから引き、もう一方では足すことで衝突検出が正しく行われたような印象が出ます。思ったとおり、壁にぶつかった時点でボールが弾むようになります。

自分のコードと比べる
----------

もう一度、このパートを終えた後にできたコードと比べてみて、それからコードで遊んでみてください。

**メモ:** 壁に当たるたびにボールの色をランダムに変えてみてください。

次のステップ
------

ボールが動き、かつゲームボードに留まるようになることまでこぎつけました。第 4 章では操作できるパドルを実装してみます。パドルとキーボード操作を見てみましょう。

* « 前のページ
* 次のページ »