WWDC Quick Look 💓 By SwiftGGTeam
Bring accessibility to charts in your app

Bring accessibility to charts in your app

元の動画を見る

ハイライト

Apple が VoiceOver にオーディオ グラフを追加し、渡すAXChartaccessibilityChartDescriptorおよびチャート記述オブジェクトを使用すると、開発者はビジュアル チャートを、再生および探索可能なアクセス可能なデータ エクスペリエンスに変換できます。

主要内容

多くのアプリケーションは、グラフを使用してデータを表示します。健康傾向、経済的変化、車の燃料消費量、出生率曲線など、ユーザーはピーク、傾向、異常を一目で確認できます。

問題は、グラフがデフォルトでビジュアルに依存していることです。視覚障害のあるユーザーは線の傾向を見ることができず、生データ ポイントの長いリストからデータの意味を迅速に判断することは困難です。

これまでの解決策は、データ ポイントをアクセシビリティ ツリーに詰め込むことが一般的でした。 VoiceOver はポイントを 1 つずつ読み上げることができますが、ユーザーは頭の中で傾向を説明する必要があります。データポイントが多すぎると、ナビゲーションが遅くなります。

Apple は WWDC21 で、より直接的な解決策を提示しました。まず、グラフ自体を VoiceOver でナビゲート可能なセマンティック コンテナーにし、次にオーディオ グラフ (オーディオ グラフ) を使用してデータ シーケンスをサウンドに変換します。値が大きいほどピッチが高くなります。値が小さいほど、ピッチが低くなります。ユーザーはカーブ全体を再生するか、ドラッグして特定の位置の特定の値を調べることができます。

この一連の機能は、同じ問題点を解決します。つまり、チャートの値は単なる単一の数値ではなく、傾向、形状、外れ値も含まれます。オーディオ グラフを使用すると、VoiceOver ユーザーはこの情報を数秒で利用できるようになります。

視覚的なチャートも最初に判読できる必要があります

図のアクセシビリティは、VoiceOver を提供するだけではありません。ロービジョンおよび色覚障害のあるユーザーも、より鮮明な視覚エンコーディングを必要としています。

Apple は、開発者が最初に 3 つのことを行うことを推奨しています。前景と背景のコントラストを改善すること、赤、緑、青と黄色などの混乱を招く色を避けること、データ系列を区別しやすいように記号を使用することです。たとえば、一方の線にドットを使用し、もう一方の線に四角形を使用すると、ユーザーは色に依存せずにカテゴリを区別できます。

製品の設計によりデフォルトのスタイルが制限されている場合は、システムのアクセシビリティ設定にも対応できます。 [色を使用せずに区別] がオンの場合はシンボルを増やします。 [コントラストを上げる] がオンの場合は、よりコントラストの高い色を使用します。 [透明度を下げる]がオンの場合、透明度を下げます。

VoiceOver はチャートに入力できる必要があります

チャート ビューは通常、独自のコンテンツを描画するだけです。 VoiceOver は、データ ポイントがいくつあるか、または各ポイントが画面上のどこにあるかを知りません。

このセッションの最初のステップは、チャート ビューをセマンティック コンテナとして宣言し、UIAccessibilityElement。これにより、ユーザーは VoiceOver を使用してデータ ポイントを 1 つずつナビゲートし、各ポイントの X 値と Y 値を聞くことができます。

オーディオ グラフはトレンドを表現する役割を担います

ポイントバイポイントナビゲーションは、「あるポイントとは何ですか?」に答えることができます。 Audio Graphs は、「この曲線はどのように見えますか?」という質問に答えます。

開発者の実装AXChartプロトコルは、AXChartDescriptor。この説明オブジェクトには、タイトル、概要、軸、およびデータ系列が含まれます。 VoiceOver がこの構造化情報を取得すると、再生、インタラクティブなドラッグ、データ値の読み取り、グラフの詳細ビューを提供できるようになります。

詳細

1. 視覚的なルールを使用して読み取りの閾値を下げる

(07:02) Apple はビジュアルデザインから始まります。グラフでは、コントラストの高い色を使用するようにしてください。講演では、Xcode に組み込まれている Accessibility Inspector の Color Contrast Calculator を使用して比率を確認し、少なくとも 4.5:1 を目指すことが提案されました。

このセクションには専用の「コード」タブ スニペットはありません。セッションで言及されたシステム設定は、検査エントリに整理できます。

import UIKit
import SwiftUI

let reduceMotionEnabled = UIAccessibility.isReduceMotionEnabled

struct ChartStyleProbe: View {
    @Environment(\.accessibilityReduceMotion) private var reduceMotion

    var body: some View {
        Text(reduceMotion ? "Reduce Motion" : "Default Motion")
    }
}

キーポイント:

  • import UIKit導入UIAccessibility
  • UIAccessibility.isReduceMotionEnabledUIKit の [モーションを減らす] 設定に対応します。
  • import SwiftUISwiftUI の環境価値システムを紹介します。
  • @Environment(\.accessibilityReduceMotion)SwiftUI で Reduce Motion 状態を読み取ります。
  • bodyシステム設定に応じて表示内容を切り替えると、同じ入り口を使用して実際のチャートのアニメーションやモーション効果を軽減できます。

(09:40) デフォルトのチャートに常にシンボルが表示されない場合は、「色なしで区別」がオンになっているときにシンボルを追加する必要があります。 [コントラストを上げる] をオンにすると、よりコントラストの高いカラーが使用されます。 「透明度を下げる」をオンにすると、透明度の効果が軽減されます。

この原則は、グラフ スタイル レイヤーに配置するのに適しています。線の色、点の形状、透明度を描画関数にハードコーディングしないでください。最初にスタイルの生成に集中し、それからそれらを描画コードに渡して使用します。

2. グラフを VoiceOver セマンティック コンテナーにします

(10:47) トーク内の例は通常のものです。ChartView始める。ビューが保持されますChartModel、モデルにはタイトルとデータポイントがあります。

class ChartView: UIView {
    let model: ChartModel

    func drawChart() {
        // ...
    }
}

struct ChartModel {
    let title: String
    let dataPoints: [DataPoint]

    struct DataPoint {
        let name: String
        let x: Double
        let y: Double
    }
}

キーポイント:

  • ChartViewカスタムチャートビューです。
  • modelグラフに表示する必要があるデータを保存します。
  • drawChart()これは、描画ロジックがすでに利用可能であることを意味し、スピーチは描画の詳細については展開しません。
  • ChartModel.titleグラフのアクセシビリティ ラベルとして使用できます。
  • dataPointsチャート上の点の集合です。
  • DataPoint.xそしてDataPoint.yそれぞれX軸とY軸の値に対応します。

(10:48) 次のステップは、チャート ビューのアクセシビリティ プロパティをオーバーライドすることです。accessibilityContainerTypeVoiceOver にこのビューが関連する要素のグループであることを伝えるために使用されます。accessibilityLabelチャートのタイトルを読み上げるために使用されます。accessibilityElementsナビゲート可能なチャート内の要素を返します。

extension ChartView {
    public override var accessibilityContainerType: UIAccessibilityContainerType {  }
    public override var accessibilityLabel: String? {  }

    public override var accessibilityElements: [Any]? {
        get {
            return model.dataPoints.map { point in
                let axElement = UIAccessibilityElement(accessibilityContainer: self)
                axElement.accessibilityValue = "\(point.x) cups, \(point.y) lines of code"
                axElement.accessibilityFrameInContainerSpace = frameRect(for: point)
                return axElement
            }
        }
        set {}
    }

 private func frameRect(for dataPoint: DataPoint) -> CGRect {

キーポイント:

  • accessibilityContainerType音声に対応するセマンティック グループ化タイプが返される必要があります。semanticGroup
  • accessibilityLabel通常、VoiceOver が現在のグラフを識別できるようにするには、グラフのタイトルを使用します。
  • accessibilityElements各データポイントをアクセス可能な要素に変換します。
  • UIAccessibilityElement(accessibilityContainer: self)要素を現在のチャート ビューの下にハングします。
  • accessibilityValueVoiceOver によって読み取られるデータ ポイントのコンテンツです。実際のプロジェクトでは、複数のルールをローカライズして処理する必要があります。
  • accessibilityFrameInContainerSpaceVoiceOver にグラフ コンテナ内のこのデータ ポイントの位置を伝えます。
  • frameRect(for:)チャートを描画するときに、既存のポイント計算ロジックを再利用できます。

(13:30) グラフに数百または数千のポイントがある場合は、ポイントごとに要素を作成しないでください。 Apple は、グラフを適切な間隔に分割し、間隔ごとにアクセシビリティ要素を作成することを推奨しています。これにより、ナビゲーション エクスペリエンスが向上し、パフォーマンスのプレッシャーが軽減されます。

3. オーディオ グラフの構造化モデルを準備する

(14:23) オーディオ グラフには、単なるポイントのリスト以上のものが必要です。 VoiceOver には、タイトル、概要、軸範囲、軸タイトルも必要です。

struct ChartModel {
    let title: String
    let summary: String
    let xAxis: Axis
    let yAxis: Axis
    let data: [DataPoint]

    struct Axis {
        let title: String
        let range: ClosedRange<Double>
    }

    struct DataPoint {
        let name: String
        let x: Double
        let y: Double
    }
}

キーポイント:

  • titleこれはチャートのタイトルであり、チャートの説明オブジェクトに入ります。
  • summaryデータから最も重要なポイントを 1 ~ 2 文で説明するグラフのような代替テキスト。
  • xAxisX軸について説明します。
  • yAxisY軸について説明します。
  • Axis.title軸名です。
  • Axis.range座標軸が表示できる最小値から最大値です。
  • dataチャートの実データです。
  • DataPoint名前、X 値、Y 値を保存してください。

17:45summary非常に批判的です。講演ではそれをグラフの代替テキストに例えています。これは Audio Graph Explorer ビューに表示され、VoiceOver ユーザーがサウンドの探索に入る前にデータの結論を把握できるようにします。

4. 実装AXChartプロトコル

(15:08) オーディオ グラフを有効にするには、まずアクセシビリティ フレームワークをインポートしてから、チャート ビューを準拠させます。AXChartプロトコル。このプロトコルでは、実装するプロパティが 1 つだけ必要です。accessibilityChartDescriptor

import Accessibility

extension ChartView: AXChart {

public var accessibilityChartDescriptor: AXChartDescriptor? {
    get {
    }
    set {}
    }
}

キーポイント:

  • import Accessibilityオーディオ グラフ関連のタイプを紹介します。
  • extension ChartView: AXChartこのビューがシステムに図の説明を提供できることを示します。
  • accessibilityChartDescriptorVoiceOver がチャート構造を取得するための入り口です。
  • getdescription オブジェクトを構築して返す必要があります。
  • set {}プロパティの書き込み可能なインターフェイスを維持します。この例では書き込みは処理されません。

このプロパティを実装すると、オーディオ グラフ エントリが VoiceOver のローターに表示されます。ユーザーは、チャートの詳細を入力したり、オーディオチャートを再生したり、対話モードに入ってドラッグして探索したりできます。

5. 軸のタイトル、範囲、値の読み取り方法を記述する

(15:35) 軸説明オブジェクトは、この軸が数値軸かカテゴリ軸か、表示範囲は何か、グリッド線はどこにあるか、値をどのように読み取るべきかなどを VoiceOver に伝えます。

public var accessibilityChartDescriptor: AXChartDescriptor? {
    get {
        let xAxis = AXNumericDataAxisDescriptor(  )
        let yAxis = AXNumericDataAxisDescriptor(title: model.yAxis.title,
                                                range: model.yAxis.range,
                                                gridlinePositions:[],
                                                valueDescriptionProvider: { value in
            return "\(value) lines of code"
        })
    }
    set {}
}

キーポイント:

  • AXNumericDataAxisDescriptor数値軸に使用されます。
  • xAxis例ではパラメータは省略しており、X 軸がカテゴリデータの場合はカテゴリ軸を使用してオブジェクトを記述する必要があることを説明します。
  • yAxis使用model.yAxis.title軸タイトルとして。
  • range: model.yAxis.rangeY 軸の表示範囲を提供します。
  • gridlinePositions: []この例ではグリッド線の位置が提供されていないことを示します。
  • valueDescriptionProviderVoiceOver が読み上げを読み上げる方法を制御します。
  • "\(value) lines of code"VoiceOver に、単なる数字を話すのではなく、単位付きの値を読み取らせます。

(16:02) グリッド線の位置が指定されている場合、オーディオ グラフは再生中およびインタラクション中に触覚フィードバックを使用してグリッド線を表します。講義の例には X 軸のグリッド線がないため、空の配列が渡されます。

6. データ系列を与えるAXChartDescriptor

(16:55) 座標軸が完成したら、データ系列も提供する必要があります。シリーズごとに 1 つを使用するAXDataSeriesDescriptor説明する。最後に、タイトル、要約、軸、シリーズを組み合わせて、AXChartDescriptor

public var accessibilityChartDescriptor: AXChartDescriptor? {
    get {
        let xAxis = AXNumericDataAxisDescriptor(  )
        let yAxis = AXNumericDataAxisDescriptor(  )
        let series = AXDataSeriesDescriptor(  )
        return AXChartDescriptor(title: model.title,
                                 summary: model.summary,
                                 xAxis: xAxis,
                                 yAxis: yAxis,
                                 additionalAxes: [],
                                 series: [series])
    }
    set {}
}

キーポイント:

  • xAxisX 軸の説明オブジェクトです。
  • yAxisY 軸の説明オブジェクトです。
  • seriesデータ系列の説明オブジェクトです。
  • AXDataSeriesDescriptorシリーズ名、連続かどうか、および実際のデータ ポイントが必要です。
  • 点またはバーとして視覚的に表現される離散データ、isContinuous引き継がれるべきfalse
  • 連続データを線で視覚的に表現、isContinuous引き継がれるべきtrue
  • AXChartDescriptor.titleグラフのタイトルを使用します。
  • summaryモデル内の要約を使用して、ユーザーにグラフィカルな結論を提供します。
  • additionalAxes: []例に追加の軸がないことを示します。
  • series: [series]データ系列を VoiceOver に渡します。

(17:24) スピーチでは、モデル内のデータをAXDataPoint配列。このステップにより、VoiceOver がグラフの実際の値を取得できるようになります。その後、オーディオ グラフはトレンドを再生し、現在位置の値を読み取り、エクスプローラー ビューにチャートの詳細を表示できます。

重要ポイント

1. ヘルストレンドグラフにオーディオグラフを追加します。

  • 作業内容: 歩数、心拍数、睡眠時間などのトレンド チャートにオーディオ再生とドラッグによる探索を追加します。
  • 実行する価値がある理由: このタイプのグラフの焦点はトレンドとピークにあり、オーディオ グラフはトレンドをピッチの変化に変換できます。
  • 開始方法: 既存のトレンド グラフ モデルを整理し、補足しますtitlesummaryxAxisyAxisとデータポイントを追加し、それをチャートビューに実装します。AXChartそしてaccessibilityChartDescriptor

2. 財務管理アプリの資産曲線に要約を追加します。

  • 作業内容: 資産、予算、経費のグラフに 1 つまたは 2 つの文のグラフの概要を追加します。
  • 価値がある理由: VoiceOver ユーザーは、Audio Graph Explorer に入る前に最も重要なデータの結論を聞くことができます。
  • 開始方法: チャートごとに生成summary最高値、最低値、増加傾向または減少傾向などのフィールドを入力し、それを に渡します。AXChartDescriptor(summary:)

3. 散布図の傾向および異常点の探索を提供します。

  • 内容: 散布図の再生可能なデータ シリーズを提供し、ユーザーが全体的な増加、減少、異常値を聞くことができるようにします。
  • 実行する価値がある理由: 講演の車の重量と燃料消費量の例は、散布図が音を通じて傾向や異常値を検出できることを示しています。
  • 開始方法: 各サンプルをAXDataPoint、使用AXDataSeriesDescriptorシリーズについて説明します。離散点プロットisContinuous使用false

4. データ集約型チャート向けのインターバルレベルの VoiceOver ナビゲーション

  • 対処方法: グラフに多数のデータ ポイントがある場合は、時間、値の範囲、またはサンプリング間隔ごとにデータをナビゲート可能なセグメントに分割します。
  • 実行する価値がある理由: ポイントごとのナビゲーションでは、VoiceOver ユーザーが何百もの要素の間を行ったり来たりすることになり、エクスペリエンスが低下し、パフォーマンスに影響を及ぼします。
  • 開始方法:accessibilityElementsすべての元のポイントを直接マッピングせず、まずそれらを適切な間隔に集約してから、UIAccessibilityElement

5. アクセシブルなグラフ スタイル スイッチのセットを作成する

  • 内容: ハイコントラストの色、シンボル、透明度、アニメーション戦略を一元管理します。
  • 価値がある理由: チャートの視覚的な読みやすさは、弱視および色覚に障害のあるユーザーに直接影響します。
  • 開始方法: 色なしで区別する、コントラストを上げる、透明度を下げる、動きを減らすなどのシステム設定を読み取り、グラフ スタイル レイヤーで色、シンボル、効果を切り替えます。

関連セッション

コメント

GitHub Issues · utterances