大多数浏览器和
Developer App 均支持流媒体播放。
-
让您 app 中的图表可供残障人士无障碍访问
图表是理解数据的重要工具,对于理解我们自己、我们的健康情况、我们的财务状况和我们身处的世界都至关重要。了解如何通过音频图形和声音数据,帮助视障人士访问您 app 中的图表。我们将向您展示如何通过通用设计原则和系统辅助功能设置来让图表更易于访问。
资源
- accessibilityReduceMotion
- Appearance Effects and Motion
- Audio graphs
- Color and Contrast
- isReduceMotionEnabled
相关视频
WWDC21
-
下载
♪播放重低音音乐♪ ♪ 嗨 我是普雷斯顿 今天我要谈的是 如何让app的图表变得更容易使用 我们先来看看今天会提到的内容 首先我们会先谈到一些 让你的图表更易于使用的好处 再来是一些原则 当你在决定 图表的视觉方面时 接下来我们会讨论如何让你的图表 使用旁白 变成可感知滑动的图表 最后我们会谈到一个新功能 叫做“语音图表” 以及如何让你的app支持它 那我们开始吧 数据在现代生活非常重要 我们每天都在使用数据 在金融 健康、目标 还有好多其他东西的决策上 但为了使用数据 我们必须要了解它 图表非常有用 因为它们让我们能快速了解 数据显示了什么 而不需要太繁琐的细节 但图表并不是无障碍的 盲人或弱视的人看不到 如果看不见视觉的图表 它就没价值了 无障碍团队研究了好多年 为了让盲人和弱视民众也能接触数据 今年 你能让你的图表 也适用在盲人和弱视民众身上 那就是让你的app支持语音图表 我们来看看范例 这是一个范例app 显示历年出生率 从1917年到1975年 但你看这个图表 你可以马上看到一些有趣的现象 你可以看到出生率降到了低点 在1935年左右 然后在差不多1960年时快速增加 之后又下降 我们能让盲人或弱视民众同样拥有 快速了解数据的能力 使用新的语音图表“旁白”功能 我来示范给你看 首先我要先找到语音图表的选单 它在旁白的齿轮里 语音图表 之后往下滑 直到听见“图表细节” 播放语音图表 图表细节 然后双击 打开语音图表的探索画面 语音图表 前往 然后我会慢慢摸索到播放键 播放语音图表 它就会播放这份数据的一段连续音 20世纪出生率 播放语音图表 按键 我们来听听看 播放完毕 是不是很令人兴奋? 你刚刚听到的 跟你看到的是同一份图表 以听觉的方式呈现而不是视觉 你听到的音高对应到历年的出生率 低音代表低数值 高音代表高数值 这些音高完全对照了视觉图表上的线 就算看不到图表 语音图表也能让你知道重要的信息 只要花短短几秒的时间 现在我们对这个数据有了大致的了解 我们来看更精确的信息 看我们有兴趣的信息 下一个我们想知道的可能是 出生率最高是大概多高 并在哪一年发生的 想这样做的话 语音图表有提供互动模式 让旁白用户可以双击屏幕后按住 再拖曳 以拖曳的速度聆听数据 如果他们停下来 旁白就会读出数值 对应到用户手指的位置 在语音图表里 我们来使用互动模式 试着找到最高的出生率及年份 20世纪出生率 数据点 1960年 每一万人有268人出生 通过在语音图表上滑动 直到听到最高的声音 然后暂停去听数值 就能知道最高的出生率 是在1960年 每一万人中就有268个新生儿 由于我们知道最高出生率 发生在1960年附近 我们可能能够推断 这个高峰对应到婴儿潮时代 我们能得到这些信息 单单从声音化的图表里 我们现在来看一个不同的图表 这是一个散布图 X轴是车辆重量 Y轴是燃油效率 来自不同种类的汽车 在这个图表的语音图表里 你听到的每个声音 都各代表一个数据点 代表一辆车 就像视觉图表的每个视觉数据点 每个声音的音高都代表 车辆每加仑英里数的燃油效率 所以高的音频代表高燃油效率的车辆 想想看你觉得会听到什么 在我播放语音图表后 我来听听 试着去听 数据是攀升还是下降 播放完毕 希望你有听出是下降 这代表越大台的汽车 燃油效率通常比较低 在这组数据中 想象一下 我们需要花多长的时间 才能了解这之间的关系 如果我们只有原始数据点的话 我们就必须要一个一个看 如果你仔细听的话 你可能会听到一个很高音的离群值 在这组数据里 它在语音图表里很突出 就像在视觉图表里一样 它是这组数据里唯一的油电混合车 如果你想得到关于离群值更多的信息 你可以使用互动模式 在数据间滑动 直到听到最高音 然后暂停 听取数值 就像我们在出生率图表做的那样 除了语音图表 这个探索画面也提供了摘要信息 关于数据中重要的信息 像是形状、趋势和离群值 是由这组图表数据的自动数据分析 推断的 连同语音图表 旁白也能读出摘要信息 来完成数据理解 我们快速回顾一下无障碍图表的优点 让你的图表更加无障碍 能让你数据丰富的app 触及到更广的群众 包含盲人和弱视民众 它能造福用户 通过使用有帮助的工具 了解图表数据 这能帮助他们好好利用数据的力量 无论是在生活或职场上 最后 加上今年要推出的新API 制作图表比以往简单更多了 我很开心能够示范给你 如何让你的app支持语音图表 但我们必须先提到 一些基本的无障碍图表主题 从如何让你的图表 在视觉上更清楚开始 你可以做一些简单的事 就让你的视觉图表更浅显易懂 以这个图表为例 这是个简单的折线图 显示每月的平均降雨量 在热带和干旱地区 我们来套用一些无障碍原则 来改善这图表的视觉亲合力 首先 使用高对比度的颜色很重要 如果可以的话 使用高对比度的前景和背景颜色 能让你的图表容易观看和理解 特别是对于弱视的人 你可以看到线条的颜色 跟背景的颜色对比度很低 标题和标签文字也都有点暗 我们来更新这些颜色 让它们跟背景 对比高一点 好多了 你可以看看颜色间的对比率 去决定这个对比是否足够 Xcode自带的“无障碍检查器” 有颜色对比计算器供你使用 最好让对比率高于4.5比1 下一步能做的是 来改善你的图表的无障碍功能 就是避免有问题的颜色组合 通常有一个好方法 就是尽可能避免红绿组合 红绿色盲是最常见的一种色盲 同时使用这两个颜色 会让你的图表对有些人来说难以理解 回到折线图 绿线代表热带地区的降雨 红线代表干旱地区的降雨 你可以知道哪个数据是哪条线 通过使用小图示 但如果你有绿色盲 一种红绿色盲的形式 这个图表可能看起来会像是这样 你很难知道 哪条线是热带地区的降雨 哪条线是干旱地区的降雨 我们把红色的线改成蓝色 这看起来可能变化不大 但对于红绿色盲的人来说 图表看起来会像这样 做一点小调整 就能让红绿色盲的人 看出两条之间的差别 还要避免同时使用蓝色跟黄色 因为这组颜色的色盲 是第二常见的 这些都是很好的改良 我们再更进一步 用符号代替颜色 来区分数据 使用数据符号能让大家 了解你的图表 且不需要依靠颜色 回到图表 我们来加一些符号到数据上 你可以看到热带的数据现在有圆点 干旱数据有方点 你现在可以辨识数据 单从符号来看 这代表就算有人分辨不出颜色 也能了解你的图表 如果一开始就这样做的话是最好 但有时候基于设计或是产品限制 你可能选择的颜色有限 或符号有限 这样的情况下 你还是能通过支持一些 简单的无障碍设定 来提供无障碍的体验 即使你的图表默认中不能使用符号 你也可以提供无障碍体验 通过开启设定 当使用颜色区分时 加入符号 如果基于产品的关系 不能随意更改颜色设定 可以考虑使用高对比度颜色 当对比增强的设定启用时 降低透明度 也能让你的图表视觉上更友好 如果你的图表使用透明效果 可以考虑关闭他们 当降低透明度 的设定开启时 如果你是在开发macOS 而不是iOS的app 你也可以在macOS 支持这些设定 你可以在这部影片的相关资料里 找到这些API的开发者文档 现在我们来看如何让你的app 变成可滑动的 通过旁白 我喜欢喝咖啡也喜欢编程 我们来假设一下它们之间有关连 一排是喝咖啡的量 一排是写的代码量 做成图表 假设而已 另外这数据显示到12杯咖啡 但别担心 没有工程师 在制作数据的时候受到伤害 这都是假的 我们来看如何让这数据变成可滑动的 给旁白用户使用 这是一段图表检视类别的范例代码 它跟模型对象相对应 图表检视应该有一个模型的参考 还有自动绘图的功能 模型可能会有图表的标题跟数据点 在一个简单的结构里 首先要做的 是把你的图表变成容器 这会帮助旁白正确地 集合你图表的元素 帮助滑动 要把你的图表变成容器 只要覆写无障碍容器类型 在图表检视上 然后回传语意群组容器类型 这对于旁白的滑动 还有找出属于图表的元素来说很重要 下一步 我们要给图表的无障碍标签 这会告诉旁白关于你的图表 要讲的内容 通常这应该是你图表的标题 或相似内容以供旁白阅读 让你在用户界面可以辨识出你的图表 最后 你需要为每个数据点 提供无障碍元素 你可以提供这些元素 通过覆写图表检视的无障碍元素属性 这会在你的图表里创建元素 让旁白可以滑动 用户就能获得 每个数据点的信息 要这样做的话 你可以使用地图 从你的数据点列表 建立你的无障碍元素陈列 每个数据点 我们都会建立一个新的 UI无障碍元素对象 指定图表检视 做为它的无障碍容器 然后我们提供一个数据点的字符串呈现 给元素的无障碍数值属性 这个字符串就是 旁白会阅读的内容 当你滑动到这些数据点上时 在你的代码中 你可能会想要本地化字符串 你可能会想使用字符串字典 来决定适当的多元化规则 在这个范例中 我们还是先保持简单就好 最后我们需要提供无障碍框架 给我们的元素 好让旁白知道 它在屏幕的位置 你可能在其他地方有计算 每个数据点框架的逻辑 因为你需要这个来绘制视觉图表 如果你手上有的话 你可以用在这里 你现在可以回传你已经完成的 数据点无障碍元素 好 我们来看看目前完成了什么 咖啡杯数对上代码条数 零杯 20条代码 一杯 30条代码 两杯 35条代码 三杯 32条代码 太好了 像你听到的 旁白读出了标题 当它聚焦在图表元素时 因为我们把图表变成语意群组 然后给它无障碍标签 我们也让每个数据点可以被滑动 通过创建UI无障碍元素 去代表每个数据点 还有一件事 有时候你可能有数百个 或数千个数据点 这种情况下 你不会想要 为每个数据点制作无障碍元素 因为这样会有太多要滑动 我们建议把你的图表 合理的间隔开来 再为每个区间 制作元素 而不是针对每个数据点 这会提供更好的滑动体验 还能带来更好的表现 同时又便于理解 还没结束哦 我们还能做更多 让数据可滑动很重要 但我们还是在呈现原始数据 给旁白用户 一次一个点 图表的价值在于告诉我们 数据真正显示了什么 帮助我们看得比单一数据点更远 这就是语音图表能做的 现在 终于到了 我们来谈谈 如何让你的app支持语音图表 想象我们有一个图表模型结构 里面包含我们用来定义特定图表 所需的信息 在你的代码中 你可能有一个模型对象 看起来像这样 如果没有 别担心 这个概念还是能套用在你的代码上 不管它是什么样 在这个例子上 一个图表会有标题跟大纲 一个X轴 一个Y轴 每个轴都有小标题跟数值范围 代表轴上呈现的最高和最低 的数值 最后 还有数据点的陈列 包含图表真正的数据 我们会使用这个范例模型对象的信息 去开启我们图表的语音图表 首先 导入无障碍框架 然后展开图表检视类别 遵守AXChart协议 遵守AXChart协议很简单 因为只需要支持一个属性 你只需要实施无障碍图表描述符 你建造的图表描述符对象 会包含旁白所需的所有信息 去提供语音图表体验 我们来看如何建造图表描述符 一步一步来 首先我们需要为每个轴 创建一个轴描述符对象 每个轴描述符会提供信息给旁白 关于它是呈现分类还是数字数据与否 呈现的数值范围 网格线的位置 还有如何安排可读数值 由于X轴在咖啡图表里是数字 我们就创建一个数字轴描述符 如果X轴是分类数据 我们就使用分类轴描述符 我们会提供标题跟数值范围 通过使用模型对象 我们也可以选择性地提供 轴上的网格线位置 如果有的话 当你提供了网格线 他们会在语音图表里以触觉回馈呈现 在播放和互动时 我们先让它空白 因为我们的X轴没有网格线 以数字轴来说 我们也需要创建 一个数值描述符提供者闭包 这个闭包很重要 因为它会告诉旁白 如何读出轴上的数值 所以它会说“五杯” 而不是只有“五” 在这轴上 我们要安排描述在数值后 读出“杯” 一样 在你的代码里 你可能会想本地化字符串 套用适当的多元化规则 但我们还是让这范例保持简单 我们要做一样的事情 创建Y轴的 轴描述符 只是我们要把数值描述 安排成读出“条代码”而不是“杯” 现在我们的图表有基本的结构了 我们来加上数据 你要为每个数据列加入 数据列描述符 这图表中只有一个数据列 所以创建一个数据列描述符就好 输入数据列名称 它是否有连续性 还有真实的数据点 你可以在连续性这边输入“否” 当数据列的视觉呈现 是使用离散标记 像点或长条时 你要输入“是” 当你的数据列的视觉呈现是线条时 以我们的数据列来说 我们需要提供AXDataPoint对象陈列 最简单的方法就是标示他们 从图表模型的数据中标示 快完成了 只剩最后一步 就是全部合在一起 建立出AXChartDescriptor对象 我们给个标题 一样 要跟图表的标题一样 如果有的话 可以提供一个大纲给我们的图表 这就像是在为图表提供替代文字 你应该用这个属性去传达 数据最重要的信息 用一两句话就好 这个大纲文字 会呈现给用户 在语音图表的探索画面 这可以大大的帮助旁白用户 理解你的图表 最后 我们会提供刚刚创建好的 轴和数据描述符来完成图表描述符 然后回传 好了 来看看最终成果 语音图表 播放语音图表 数据细节 语音图表 前往 咖啡杯数对上代码条数 播放语音图表 按键 播放完毕 回顾重点 记得要为你图表视觉设计 加上无障碍功能选择 这包含使用良好的对比率 除了颜色外 使用符号 来区分数据类别 避免使用有问题的颜色搭配 为了色盲用户 记得要在无障碍功能树 公开数据元素 让旁白用户可以感知并滑动 最后 实施AXChart协定 还有无障碍图表描述符 在图表检视上 让旁白用户 可以获得跟视觉用户一样的图表数值 现在你知道了所有信息 可以去创建丰富、无障碍的图表了 我们希望你能使用这些工具 来更好地帮助用户 因为数据在现代生活真的很重要 图表是最好的工具之一 用来在充满数据的世界里了解数据 现在 你能把这好处带给所有人了 ♪
-
-
10:47 - Chart Model
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 } }
-
10:48 - ChartView
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 {
-
14:23 - Basic chart definition example
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 } }
-
15:08 - Enabling Audio Graphs
import Accessibility extension ChartView: AXChart { public var accessibilityChartDescriptor: AXChartDescriptor? { get { } set {} } }
-
15:35 - Chart Descriptor- Basic
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 {} }
-
16:55 - Chart Descriptor- Continued
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 {} }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。