チュートリアル アクセシブルなキャンバスの説明を書く

アクセシブルなキャンバスの説明を書く

By Kathryn Lichlyter, Layla Quiñones

はじめに

このチュートリアルでは、describe()describeElement()textOutput()gridOutput()の使い方を学びます。これらの関数は、スクリーンリーダーで読み取れるようにキャンバスにラベルを追加します。

ラベリングとは

createCanvas()関数を使用すると、キャンバスのHTML要素が作成されます。このキャンバス要素は、コードによって生成された画像をビットマップ(ピクセルで構成されたラスターグラフィック)として表示します。デフォルトでは、キャンバスはその内容についてスクリーンリーダーに説明を提供しません。そのため、describe()describeElement()textOutput()gridOutput()関数を作成しました。これらの関数は、スクリーンリーダーがキャンバスをどのように説明すべきかを伝えるラベルを追加します。

ラベリングが重要な理由

スクリーンリーダーは多くの人々にとって役立ちます。サイトのコードが支援技術向けに適切にラベル付けされていない場合、スクリーンリーダーソフトウェアはサイトの内容を伝えることができません。コードが支援ソフトウェアで読み取れるようにすることで、より多くの人々が意味のある方法であなたの作品に関わることができます。

利用可能なラベリング関数

p5.jsはキャンバスのラベリングのために4つの異なる関数を提供しています:

  • describe()は、キャンバスの内容の説明を提供します。この関数のパラメータには、ラベル自体を表すtextと、ラベルの表示/非表示を設定するオプションのパラメータdisplayがあります。
  • describeElement()は、キャンバス内の特定の要素または要素のグループを説明します。この関数のパラメータには、ラベルのタイトルとなるname、ラベル自体を表すtext、そしてラベルの表示/非表示を設定するオプションのパラメータdisplayがあります。
  • textOutput()は、キャンバスのサイズ、色、および各視覚要素の色、位置、キャンバス内で占める領域を説明するリストを生成します。この関数の唯一のパラメータは、ラベルの表示/非表示を設定するオプションのdisplayです。
  • gridOutput()は、textOutput()と同様に、キャンバスの特性と要素のリストを生成します。このリストに加えて、この関数はキャンバス内の各形状の空間的位置をプロットするHTMLテーブルも作成します。この関数の唯一のパラメータは、ラベルの表示/非表示を設定するオプションのdisplayです。

前提条件

ラベリングを始める前に、プロジェクトのコードはほぼ完成している必要がありますが、最初からラベリングを念頭に置いておくべきです。明確で効果的なラベルを書くために、キャンバス要素内でコードが作成する視覚的な要素について明確な理解が必要です。

例えば、キャンバスの結果として生成される視覚的な要素について明確な理解がないままラベルを書き始めると、以下のコード例のように、ラベルと視覚的な要素が異なるメッセージを伝えてしまう可能性があります:

js
function setup() {
  createCanvas(100, 100);
  describe('黒いキャンバスの中央に青い四角形があります。');
}

function draw() {
  background(255, 192, 203);
  noStroke();
  fill(200,0,0);
  ellipse(67, 67, 20, 20);
  ellipse(83, 67, 20, 20);
}

ステップ1 — ラベリング戦略を計画する

ラベリング戦略は、プロジェクトの複雑さと目的に応じて変更する必要があります。

コードにラベルを提供しない場合、スクリーンリーダーはキャンバスを空のHTML要素として説明します。プロジェクトがどれほど複雑であっても、必ずsetup()内でdescribe()関数を使用してキャンバスの簡単な説明を提供してください。

describe()関数内では、テキストパラメータにキャンバスの1-3文の説明を提供してください。この説明は、キャンバスの視覚的な要素についての詳細のみを提供する必要があります。

function setup() {
  createCanvas(100, 100);
  describe('ピンクの背景の右下に赤いハートがあります。');
}

function draw() {
  background(255, 192, 203);
  noStroke();
  fill(200,0,0);
  ellipse(67, 67, 20, 20);
  ellipse(83, 67, 20, 20);
  triangle(91, 73, 75, 95, 59, 73);
}

スクリーンリーダーはラベルを読み上げる前に要素の種類を宣言するため、説明を「p5キャンバス要素…」などで始める必要はありません。

describe()ラベルを使用してキャンバス全体を説明してください。コード内の特定の要素により詳細なラベルを追加するには、describeElement()textOutput()、またはgridOutput()関数を使用してください。

describe()describeElement()関数では、キャンバスの視覚的な要素のテキスト説明を自由に作成できます。textOutput()gridOutput()関数は、キャンバスのサイズ、色、および各視覚要素の色、位置、キャンバス内で占める領域をリストとして自動的に説明します。describe()describeElement()とは異なり、textOutput()gridOutput()関数は形状の使用意図を解釈できません。どの関数を使用するかを選択する際は、コンテキストを考慮してください。textOutput()gridOutput()を使用して花を「8つの円と1つの長方形」として説明するのと、describe()またはdescribeElement()を使用して「赤い花びらと緑の茎を持つ花」として説明するのと、どちらが良いでしょうか?どのようなラベリングがキャンバスの最適な説明を提供するでしょうか?多くの形状を持つより大きな視覚的要素を作成している場合は、describeElement()を使用して各形状グループが何であるかをラベル付けすることをお勧めします。

同じキャンバスを説明するためにtextOutput()gridOutput()の両方の関数を使用しないでください。両方を使用すると、類似した説明が2回表示され、スクリーンリーダーでの解釈が困難になります。同様に、textOutput()またはgridOutput()describeElement()ラベルと一緒に使用することも避けてください。describe()ラベルを補完するために、これらの関数の1つだけを選択することをお勧めします。

複雑なプロジェクト

以下の場合は、p5のラベリング関数の代わりに通常のARIAラベリングとカスタムビルドのフォールバックラベルを使用してください:

  • 外部のインタラクティブ要素(キャンバス外の要素)を介してコンテンツが大幅に変更される場合
  • キャンバスコード外で書かれたDOM要素と相互作用する場合
  • キャンバスの視覚的なコンテンツが変更された場合にユーザーの注意が必要な場合
  • describe()describeElement()textOutput()、またはgridOutput()関数で正確にラベル付けできない複雑な要素レイアウトがある場合

フォールバックコンテンツの詳細については、W3Cのウィキを参照してください。複雑なARIAラベリングについては、Mozillaの「ARIAの状態とプロパティ」W3Cの「ARIAの使用」MDNのARIAを参照してください。

ステップ2 — メインラベルとサポートラベルを書く

ユーザーに最適なサービスを提供する関数を使用してキャンバスのラベリングを開始します。

ラベリングの際は、キャンバスの視覚的な側面の説明のみを提供してください。キャンバス上に表示される最終的な視覚的要素がどのように見えるかのみを説明し、視覚的要素を作成する関数やその方法については説明する必要はありません。

describeElement()の使用

時にはdescribe()ラベルだけではキャンバスの視覚的要素を説明するのに十分ではない場合があります。describe()を使用してキャンバスの視覚的要素を適切に詳細に説明できない場合は、describeElement()ラベルを使用して視覚的要素の個別の説明を提供してください。

describeElement()の説明は、キャンバスのdescribe()ラベルで提供された情報と矛盾してはいけません。describeElement()ラベルには一意のタイトルと1-2文の説明が必要です。キャンバスの最も重要な視覚的側面を描写するコードの部分のみにラベルを付けるようにしてください。

describeElement()ラベル内で、その要素の重要な特性について説明してください。要素はアニメーション化されていますか?要素はインタラクティブですか?要素はプロジェクトにどのような意味を提供しますか?

キャンバスに画像の全体的な理解に重要なtext()要素が含まれている場合は、それらに対して別のラベルを作成してください。読みやすいテキストには引用符を付けてラベル付けしてください。例:describeElement('Text', '黒いキャンバスの中央に緑色で表示された"hello, world"という言葉。')

前述のように、各ラベルを「p5キャンバス…」などで始める必要はありません。スクリーンリーダーはラベルを読み上げる前に要素の種類を呼び出します:

function setup() {
  createCanvas(100, 100);

  //キャンバスの全体的な説明を提供します。
  describe('ピンクの背景の右下に赤いハートと右上にテキストがあります。');
}

function draw() {
  background(255, 192, 203);
  noStroke();
  fill(200, 0, 0);
 
  textSize(12);
  textStyle(NORMAL);
  // テキストの特定のラベル
  describeElement('テキスト', 'ピンクのキャンバスの左上に"Hello world!"というテキストがあります。');
  text('Hello world!', 5, 30);
  // ハートの特定のラベル
  describeElement('ハート', '右下に赤いハートがあります。');
  ellipse(67, 67, 20, 20);
  ellipse(83, 67, 20, 20);
  triangle(91, 73, 75, 95, 59, 73);
}

コード内のdescribeElement()関数の使用はできるだけ制限してください。キャンバスを説明するために10個以上のdescribeElement()関数を使用する必要がある場合は、より複雑性に対応できるラベリング戦略(通常のARIAラベリングなど)の使用を検討してください。

textOutput()またはgridOutput()の使用

textOutput()gridOutput()は、サイズ、色、形状など、視覚要素のコードに基づいてラベル情報を自動的に計算します。describeElement()とは異なり、キャンバスのすべての視覚要素を説明するために1つのラベルだけを使用する必要があり、設定するパラメータはラベルを有効にするdisplayだけです。

textOutput()gridOutput()によって提供される情報は、スクリーンリーダーがアクセスできる非表示のdiv内に自動的に生成されます。これらの関数がコードをどのように解釈しているかを確認したい場合は、LABEL引数を使用してキャンバスの下のスペースに出力を表示することができます。

アニメーションまたはインタラクティブな要素を持つプロジェクト

HTMLボタン、ドロップダウン、入力などの個々のインタラクティブ要素にはラベルは必要ありません。これらの要素はp5.jsキャンバスの外部に構築され、スクリーンリーダーによって解釈されます。つまり、textOutput()gridOutput()関数はこれらのインタラクティブな入力に関する情報を提供しません。

キャンバス要素がアニメーション化されているか、インタラクティブな場合は、その現在の状態や特性をラベルで表現してください。関数をdraw()関数内に配置する限り、形状の新しい情報で自動的に更新されます。describeElement()を使用している場合は、テンプレート文字列を使用して要素の説明を更新してください:

let x = 0;
function setup() {
  createCanvas(100, 100);
}

function draw() {
  if (x > 100) {
    x = 0;
  }
  background(220);
  fill(0, 255, 0);
  ellipse(x, 50, 40, 40);
  x = x + 0.1;
  // ラベルは形状の移動に合わせて更新されます
  describe(`x座標${round(x)}の位置にある右に移動する緑の円`, LABEL);
}

ラベリングのDo’sとDon’ts

Don’t スクリーンリーダーのラベルをコードのコメントとして使用しないでください。ラベルはキャンバス内の結果として生成される視覚要素のみを要約する必要があります。

function setup() {
  createCanvas(100, 100);
  //キャンバスの全体的な説明を提供します。
  describe('このハートは2つの円と三角形を重ねて作られています。');
}
function draw() {
  background(255, 192, 203);
  noStroke();
  fill(200, 0, 0);
  ellipse(67, 67, 20, 20);
  ellipse(83, 67, 20, 20);
  triangle(91, 73, 75, 95, 59, 73);
}

Don’t スクリーンリーダーのラベルを過剰に使用しないでください。スクリーンリーダーのキャンバスの解釈を助けるのではなく、複雑にしてしまう可能性があります。

function setup() {
  createCanvas(100, 100);
}
function draw() {

  //視覚要素を構築するために使用される各関数にdescribeElement()を使用しないでください。
  background(255, 192, 203);
  describeElement('Heart', 'ハートにストロークは適用されていません。');
  noStroke();
  describeElement('Heart', 'ハートは赤色です。');
  fill(200, 0, 0);
  describeElement('Heart', 'ハートの上部は2つの円です。');
  ellipse(67, 67, 20, 20);
  ellipse(83, 67, 20, 20);
  describeElement('Heart', 'ハートの下部は三角形です。');
  triangle(91, 73, 75, 95, 59, 73);
}

Do ラベルの説明を短く正確にしてください。ラベルの説明の推奨される長さは1〜2文です。ラベルには完全な文を使用し、要素を説明する際は現在形で書いてください。

ステップ3 — ラベルをテストする

スケッチを公開する前に、必ずラベルをテストしてください。デフォルトでは、ラベルは表示されず、スクリーンリーダーでのみ表示可能です。開発中にラベル出力を確認するには、ラベリング関数の最後の引数としてLABELを渡してください。

function setup() {
  createCanvas(100, 100);
}
function draw() {
  // LABELはキャンバスの横にラベルを表示します。
  gridOutput(LABEL);
 
  background(255, 192, 203);
  noStroke();
  fill(200, 0, 0);
 
  ellipse(67, 67, 20, 20);
  ellipse(83, 67, 20, 20);
  triangle(91, 73, 75, 95, 59, 73);
}

ラベルをテストする際は、以下の質問を考慮してください:

  • キャンバスのラベルは、スケッチがどのように見えるか、その目的を理解するのに十分な情報を提供していますか?
  • このキャンバスが他のコンテンツと共にウェブページ上に存在する場合、ページの訪問者はキャンバスが周囲のコンテキストとどのように関連しているかを十分に理解できますか?

出力をテストしたら、必ずLABEL引数を削除してください。LABELが有効な場合、スクリーンリーダーはキャンバスにフォーカスが当たった時にフォールバックテキストと表示されているラベルテキストの両方を読み上げることを強制されます。これにより、不必要な情報の繰り返しが発生します。

スクリーンリーダーを有効にするかダウンロードしてコードをテストすることができます。MacOSにはVoiceOverという組み込みのスクリーンリーダーがあり、PCには無料でダウンロード可能なオプションがあります。スクリーンリーダーの使用に関する詳細については、W3 Schoolの「アクセシビリティスクリーンリーダー」を参照してください。

結論

ラベルをテストしたら、キャンバスはスクリーンリーダー技術でアクセス可能になるはずです!これは、より多くの人々があなたのプロジェクトに意味のある形で関わることを可能にするコミュニティケアの行為です。あなたは、よりインクルーシブでバリアフリーなインターネットに貢献する実践をモデル化しています。

p5.jsとアクセシビリティについてさらに学ぶには、スクリーンリーダーでp5.jsを使用する方法を読んでください。