Slide 1

Slide 1 text

Accessibility for Swift Charts Mika Ito, Nikkei Inc.

Slide 2

Slide 2 text

⾃⼰紹介 Mika Ito ● ⽇本経済新聞社で働いています ● iOS 開発 1.5 年⽬ ● iOSDC 2 回⽬ 2

Slide 3

Slide 3 text

Swift Charts とは ● チャートを描画するためのフレームワーク ● 簡潔なコードで簡単にチャートを作成できる ● ⾃動的にデータに応じたスケールと軸が⽣成される ● (基本的に) iOS 16.0+, iPadOS 16.0+ 3 https://developer.apple.com/documentation/charts

Slide 4

Slide 4 text

Swift Charts とは ● Marks ○ 折れ線グラフ ○ 散布図 ○ 棒グラフ ○ 円グラフ (iOS 17.0+) ○ ヒートマップ ○ … ● Vectorized plots (iOS 18.0+) 4 https://developer.apple.com/documentation/charts, https://developer.apple.com/jp/videos/play/wwdc2024/10155/

Slide 5

Slide 5 text

Accessibility of a chart VoiceOver / Audio Graphs 5

Slide 6

Slide 6 text

Accessibility of a chart VoiceOver / Audio Graphs 6

Slide 7

Slide 7 text

チャートの VoiceOver 7 ● グラフのデータポイントにカーソルを 合わせると値を読み上げてくれる ● 例えば歩数アプリだと...

Slide 8

Slide 8 text

チャートの VoiceOver 8 ● グラフのデータポイントにカーソルを 合わせると値を読み上げてくれる ● 例えば歩数アプリだと... ⚠ ⾳が流れます

Slide 9

Slide 9 text

チャートの VoiceOver 9 ● グラフのデータポイントにカーソルを 合わせると値を読み上げてくれる ● 例えば歩数アプリだと... 🔈「2024年6⽉ 歩数 1⽇の平均 4099 歩」

Slide 10

Slide 10 text

Accessibility of a chart VoiceOver / Audio Graphs 10

Slide 11

Slide 11 text

Accessibility of a chart VoiceOver / Audio Graphs 11

Slide 12

Slide 12 text

チャートのオーディオグラフ ● グラフのデータを⾳声に変換する ● x 軸を時間、y 軸をピッチとして表す ○ ⼤きな値は⾼い⾳ ○ ⼩さな値は低い⾳ ● 連続的なデータは連続した⾳ ● 離散的なデータは離散的な⾳ 12

Slide 13

Slide 13 text

オーディオグラフを聞いてみる ● 連続的な値のデータ ○ 株価、⼭の標⾼など... 13 Apple 標準の株価アプリから引用

Slide 14

Slide 14 text

オーディオグラフを聞いてみる ● 連続的な値のデータ ○ 株価、⼭の標⾼など... ⚠ ⾳が流れます ※ オーディオグラフはグラフ全体に対して 流れます。四⾓の範囲はオーディオグラフが 流れる範囲ではありません。 14 Apple 標準の株価アプリから引用

Slide 15

Slide 15 text

オーディオグラフを聞いてみる ● 連続的な値のデータ ○ 株価、⼭の標⾼など... ⚠ ⾳が流れます ※ オーディオグラフはグラフ全体に対して 流れます。四⾓の範囲はオーディオグラフが 流れる範囲ではありません。 15 Apple 標準の株価アプリから引用

Slide 16

Slide 16 text

オーディオグラフを聞いてみる ● 離散的な値のデータ ○ スクリーンタイム、歩数など... 16

Slide 17

Slide 17 text

オーディオグラフを聞いてみる ● 離散的な値のデータ ○ スクリーンタイム、歩数など... ⚠ ⾳が流れます ※ オーディオグラフはグラフ全体に対して 流れます。四⾓の範囲はオーディオグラフが 流れる範囲ではありません。 17

Slide 18

Slide 18 text

オーディオグラフの他の機能 チャートの詳細 📢 ● チャートの詳細モーダルが現れる → ● オーディオグラフも再⽣できる ● データの傾向や統計情報を⾃動⽣成 ○ 相関関係 ○ 最⼤値、最⼩値、平均値 ● インタラクティブモードが使⽤できる ○ 詳しくは WWDC21の動画 18

Slide 19

Slide 19 text

オーディオグラフの他の機能 チャートを説明 📢 ● 「x 軸は ~ です。」 ● 「y 軸は ~ です。」 ● 「~ 個のデータ系列があります。」 19

Slide 20

Slide 20 text

VoiceOver / Audio Graphs の起動⽅法 1. VoiceOver を起動する ○ 💡 簡単に起動できるようにしておくと便利 ○ 💡 私は電源ボタン3回クリックにアクセシビリティのショートカットを割り当てています 2. ローターの中から「オーディオグラフ」のメニューを探す ○ ⼆本指で捻る動き、ちょっと難しい 3. 下にスワイプでメニューを切り替える ○ オーディオグラフを再⽣ ○ チャートの詳細 ○ チャートを説明 4. ダブルタップで選択 20 https://support.apple.com/ja-jp/111796

Slide 21

Slide 21 text

どうしてこのような機能があるのか? チャートはデータの傾向をビジュアルで理解できるため、とても便利! ● 視覚的に表現されたチャートは⽬で⾒ることが前提 ● 視覚障がい者や弱視の⼈にとっては利⽤が困難 → ⾳の⾼低でデータを表現することで、⾳声としてデータの傾向や特徴を捉える ことが可能になる。 VoiceOver / Audio Graphs を使⽤して、全ての⼈が同じ情報にアクセスできる ようにしよう!! 21

Slide 22

Slide 22 text

【実践】Swift Charts のアクセシビリティ対応 22

Slide 23

Slide 23 text

開発中の動作確認⽅法 Swift Charts の VoiceOver を確認する⽅法 ● Accessibility Inspector を使⽤する ○ Xcode の Open Developer Tool から ○ 💡実機と挙動が違うことがあるので、最終的には実機で検証する必要がある ● 実機で検証する Swift Charts の Audio Graphs を確認する⽅法 ● 実機で検証する 23

Slide 24

Slide 24 text

【準備】Swift Charts でグラフを作成 struct Climate: Identifiable { var id: UUID = .init() var month: Int var precipitation: Double } var body: some View { Chart { ForEach(data, id: \.id) { item in BarMark( x: .value("Month", item.month), y: .value("Precipitation", item.precipitation) ) } } .chartXAxisLabel("月") .chartYAxisLabel("降水量") ... } 24 https://www.data.jma.go.jp/stats/etrn/view/nml_sfc_ym.php?prec_no=44&block_no=47662&year=2023&month=&day=&view=

Slide 25

Slide 25 text

まずは現状を把握する 25 アクセシビリティ対応していなくても、VoiceOver, Audio Graphs 共に利⽤できる → Swift Charts は VoiceOver, Audio Graphs を⾃動サポートしている! しかしながら、最低限の読み上げがサポートされているだけで細かい問題点はあ るので、アクセシビリティ対応していく!

Slide 26

Slide 26 text

アクセシビリティラベルを適切に付与しよう! 26

Slide 27

Slide 27 text

Accessibility Inspector で確認してみると...🤔 【VoiceOver】グラフの値の読み上げの問題 27

Slide 28

Slide 28 text

Accessibility Inspector で確認してみると...🤔 【VoiceOver】グラフの値の読み上げの問題 28 ● 単位がないので何の値なのかわかりにくい ● 降⽔量は Double なのに⼩数点以下が読み上げられ ていない ● x 軸の値(Label)が「7 to (から) 8」などと読まれ てしまう

Slide 29

Slide 29 text

アクセシビリティラベルを付与して解決 var body: some View { Chart { ForEach(data, id: \.id) { item in BarMark( x: .value("Month", item.month), y: .value("Precipitation", item.precipitation) ) .accessibilityLabel("\(item.month) 月") .accessibilityValue("\(String(format: "%.1f", item.precipitation)) ミリメートル") } } .chartXAxisLabel("月") .chartYAxisLabel("降水量") ... } 29 ● 単位を追加 ● ⼩数点第⼀位まで読み上げ られるように ✅

Slide 30

Slide 30 text

【VoiceOver】グラフの値の読み上げを再度確認 Accessibility Inspector で確認してみると... 良さそう👍 30 ✅

Slide 31

Slide 31 text

露出するコードがあることに注意! 31

Slide 32

Slide 32 text

【Audio Graphs】 軸の説明が英語で読み上げられてしまう問題 実機でオーディオグラフを確認してみると...🤔 32

Slide 33

Slide 33 text

【Audio Graphs】 軸の説明が英語で読み上げられてしまう問題 実機でオーディオグラフを確認してみると...🤔 ⚠ ⾳が流れます 33

Slide 34

Slide 34 text

【Audio Graphs】 軸の説明が英語で読み上げられてしまう問題 実機でオーディオグラフを確認してみると...🤔 各軸の説明が英語になっている! 🔈「X 軸は Month です」 🔈「Y 軸は Precipitation です」 34

Slide 35

Slide 35 text

var body: some View { Chart { ForEach(data, id: \.id) { item in BarMark( x: .value("Month", item.month), y: .value("Precipitation", item.precipitation) ) .accessibilityLabel("\(item.month) 月") .accessibilityValue("\(String(format: "%.1f", item.precipitation)) ミリメートル") } } .chartXAxisLabel("月") .chartYAxisLabel("降水量") ... } value に指定するラベルが読まれてしまっている 35

Slide 36

Slide 36 text

var body: some View { Chart { ForEach(data, id: \.id) { item in BarMark( x: .value("月", item.month), y: .value("降水量", item.precipitation) ) .accessibilityLabel("\(item.month) 月") .accessibilityValue("\(String(format: "%.1f", item.precipitation)) ミリメートル") } } .chartXAxisLabel("月") .chartYAxisLabel("降水量") ... } value に指定するラベルを修正して解決 36 ここも読まれるので、⽇本語に変更 ✅

Slide 37

Slide 37 text

多⾔語対応するのなら ラベルは LocalizedStringKey なので、String Catalog に訳語を追加して利⽤する こともできる 37 let accessibilityValueUnit: LocalizedStringResource = "millimeter" let xAxisTitle: LocalizedStringResource = "Month" let yAxisTitle: LocalizedStringResource = "Precipitation" // 使う時はこんな感じ BarMark( x: .value(String(localized: xAxisTitle), item.month), y: .value(String(localized: yAxisTitle), item.precipitation) ) ✅

Slide 38

Slide 38 text

AXChartDescripter を活⽤しよう! 38

Slide 39

Slide 39 text

チャートの詳細で出現するモーダルを確認すると...🤔 ● タイトルが「グラフ」になっている ● 概要が空になっている 【Audio Graphs】タイトルと概要が空 39

Slide 40

Slide 40 text

AXChartDescripter を活⽤する 40 https://developer.apple.com/documentation/accessibility/axchartdescriptor/init(title:summary:xaxis:yaxis:additionalaxes:series:)

Slide 41

Slide 41 text

AXChartDescripter を活⽤する 41 public struct ChartDescriptor: AXChartDescriptorRepresentable { public func makeChartDescriptor() -> AXChartDescriptor { ... return AXChartDescriptor( title: "東京都の月間降水量", summary: "東京都の降水量の平年値を月ごとに示しています。 ", xAxis: xAxis, yAxis: yAxis, series: series ) } } var body: some View { Chart { ... } .accessibilityChartDescriptor( ChartDescriptor(...) ) } ✅

Slide 42

Slide 42 text

【Audio Graphs】タイトルと概要が設定された 42 ✅

Slide 43

Slide 43 text

チャートのアクセシビリティ対応する時に意識すること ● どんなデータなのか、どう伝えたいかを意識する ● 明確に、かつ包含的に ○ ⽇付や単位を補完する ● 主観的な⽤語の使⽤は避ける ○ 「急速に」「徐々に」「ほとんど」などは使⽤しない ● 曖昧になりやすい形式や略語を避ける ○ 6/6 ではなく6⽉6⽇、6m ではなく 6 メートル など ○ スラッシュは「スラッシュ」と読まれてしまうので最終的には実機で検証することが⼤事 43

Slide 44

Slide 44 text

⾒えなかったものが”⾒えて”くる ● 機能⾯ ○ VoiceOver を使⽤すると露出するコードがある ○ 最⼤値、最⼩値、平均値がわかる ● チャートの視覚的な直感性と⾳の直感性 ○ ⾒慣れたグラフも⾳にすると興味深い ○ 実は情報処理の点で、聴覚は視覚に勝る 44

Slide 45

Slide 45 text

⾒慣れたグラフも⾳にすると興味深い ● 8 ⽉上旬の⽇経平均株価(Apple の株価アプリから) 45

Slide 46

Slide 46 text

⾒慣れたグラフも⾳にすると興味深い ● 8 ⽉上旬の⽇経平均株価(Apple の株価アプリから) ⚠ ⾳が流れます ※ オーディオグラフはグラフ全体に対して 流れます。四⾓の範囲はオーディオグラフが 流れる範囲ではありません。 46

Slide 47

Slide 47 text

Next steps ● Apple 標準アプリのチャートで VoiceOver / Audio Graphs を試してみる ● もし⾃⾝のプロダクトにチャートがあるなら、 VoiceOver / Audio Graphs を試して現状を把握する ● 今⽇学んだことを踏まえて、アクセシビリティ対応をしよ う!! 47

Slide 48

Slide 48 text

⾒えなかったものが”⾒えて”くる?😺 48

Slide 49

Slide 49 text

⾒えなかったものが”⾒えて”くる?😺 49 ⚠ ⾳楽が流れます

Slide 50

Slide 50 text

References ● https://developer.apple.com/documentation/charts ● https://developer.apple.com/documentation/Accessibility/audio-graphs ● https://developer.apple.com/jp/videos/play/wwdc2024/10155/ ● https://developer.apple.com/videos/play/wwdc2022/110340 ● https://developer.apple.com/jp/videos/play/wwdc2021/10122/ ● https://support.apple.com/ja-jp/111796 ● https://developer.apple.com/documentation/accessibility/representing-chart-data-as-an-audio-graph ● https://swiftwithmajid.com/2023/02/28/mastering-charts-in-swiftui-accessibility/ ● https://www.data.jma.go.jp/stats/etrn/view/nml_sfc_ym.php?prec_no=44&block_no=47662&year=2023& month=&day=&view= 50