跳到主要内容

语义(Semantics)

语义目前仅在抢先体验中可用。运行时支持正在开发中,或已作为实验性功能发布。

有反馈?加入抢先体验社区分享你的想法,帮助塑造此功能。

本页介绍如何在新版 Web (JS) 运行时中启用语义,让你的 Rive 图形可被屏幕阅读器访问。要了解什么是语义以及如何将其添加到图形中,请参阅编辑器文档中的语义

概述

在 Rive 编辑器中,你可以为图形的某些元素添加语义含义——例如 button、checkbox、tab、image、list、dialog 等角色,以及相关的标签、值、状态和动作。这些设置因角色而异。

在运行时,Web (JS) 运行时会从正在运行的状态机中读取这些语义,并在你的 <canvas> 旁边构建一个不可见的 DOM 树,随着状态机推进保持同步。

由于 <canvas> 对辅助技术(AT)是不透明的,这个 DOM 叠加层正是使你的图形可被发现的关键。每个语义节点都成为一个真实的 DOM 元素,具有匹配的 ARIA 角色、属性和键盘处理程序,并定位在 Rive 图形中对应节点的上方。

⚠️

语义是选择启用的。默认模式为 SemanticMode.Disabled,因此在启用语义之前不会创建任何语义 DOM。作为实验性 API,semanticsModesemanticsOptions 可能会在不进行主版本升级的情况下更改行为。

必须在编辑器中定义语义才会产生效果。如果元素没有语义,则不会暴露给屏幕阅读器——无论你设置什么模式。请参阅功能支持,了解当前哪些运行时支持语义。

语义模式

语义由 SemanticMode 枚举控制,你从 Rive 包中导入该枚举,并在实例化 Rive 时作为参数传递:

模式说明
SemanticMode.Disabled默认。 禁用语义。不会创建语义树或无障碍 DOM。
SemanticMode.Enabled语义已激活。无障碍 DOM 在加载后创建,并随着状态机推进保持更新。

用法

导入 SemanticMode,并在实例化 Rive 时将其作为 semanticsMode 传递。

import { Rive, SemanticMode } from "@rive-app/webgl2";

const rive = new Rive({
canvas: document.getElementById("rive-canvas"),
src: "login.riv",
stateMachines: "State Machine 1",
autoplay: true,
autoBind: true,
semanticsMode: SemanticMode.Enabled,
});

加载后启用语义

如果你想以编程方式控制何时启用语义,可以在构造 Rive 时使用默认的 SemanticMode.Disabled,并在用户选择启用时调用 enableSemantics() 方法。

const rive = new Rive({
canvas: document.getElementById("rive-canvas"),
src: "login.riv",
stateMachines: "State Machine 1",
semanticsMode: SemanticMode.Disabled,
autoplay: true,
autoBind: true,
});

accessibilityToggle.addEventListener("change", (event) => {
if (event.target.checked) {
rive.enableSemantics();
}
});

标注图形

语义叠加层的容器元素是一个 role="region" 地标。在实例化 Rive 时使用 semanticsOptions.riveCanvasLabel 参数为其设置一个 aria-label,描述图形是什么,以便屏幕阅读器用户知道他们正在进入什么。

const rive = new Rive({
canvas: document.getElementById("rive-canvas"),
src: "login.riv",
stateMachines: "State Machine 1",
autoplay: true,
autoBind: true,
semanticsMode: SemanticMode.Enabled,
semanticsOptions: {
riveCanvasLabel: "Login Experience",
},
});
选项类型说明
riveCanvasLabelstring应用于叠加层容器的 aria-label。默认为 "Rive animation"

语义如何映射到 DOM

运行时将每个编辑器语义角色转换为 ARIA 角色,将每个状态和特征转换为匹配的 ARIA 属性。在大多数情况下,这些属性附加到 <div> 元素上,以在各浏览器中统一样式/布局模式。文本内容包裹在内部 <span> 中,以辅助 AT 浏览文本。

⚠️

在语义功能处于抢先体验阶段时,这组角色和特征可能会发生变化。

编辑器角色DOM 输出
Buttonrole="button"
Checkboxrole="checkbox"
Switchrole="switch"
Sliderrole="slider"
Text文本作为 DOM 文本内容存在于内部 <span> 中,父级为 <div>。对于标题,<div> 具有 role="heading" 并设置 aria-level
Imagerole="img",但必须有标签
Group / Nonerole="group"
List / List itemrole="list" / role="listitem"
Tab / Tab listrole="tab" / role="tablist"
Dialog / Alert dialogrole="dialog"aria-modal(模态时)/ role="alertdialog" 始终带 aria-modal
Radio group / Radio buttonrole="radiogroup" / role="radio"

状态和特征映射到 ARIA 属性,如 aria-expandedaria-selectedaria-checkedaria-pressedaria-requiredaria-disabled。只有当编辑器中存在相应特征或 ARIA 要求其存在时,才会设置属性,因此 AT 看到的是"不适用"而非"false"。

  • 标签(Label) 变为 aria-label(对于文本节点则变为 DOM 文本内容)。
  • 提示(Hint) 变为视觉隐藏的描述,通过 aria-describedby 引用。
  • 滑块的值(Value) 变为 aria-valuenowaria-valuetext
  • 隐藏(Hidden) 变为 aria-hidden="true"
  • 实时区域(Live Region) 变为 aria-live="polite"

没有标签的图像被视为装饰性图像,会对辅助技术隐藏,因为没有可访问名称的 role="img" 元素不符合 WCAG 标准。请在编辑器中为任何有意义的图像添加标签。

其他注意事项

Tab Index

可交互、可聚焦和列表项叠加层元素被赋予 tabindex="-1",这使它们不在浏览器的顺序 Tab 导航中;其余元素不携带 tabindex。这些元素仍可被屏幕阅读器的光标访问,但仅使用键盘的视力用户无法 Tab 到图形内的单个元素。

语义叠加层定位

Rive 会在画布调整大小或移动时保持叠加层与画布匹配。运行时会监视画布、其父级和窗口的变化并重新同步叠加层,因此常见场景无需额外工作。

叠加层容器作为 <canvas> 的兄弟节点插入,并使用画布的布局偏移进行定位。如果可能,请为画布的容器设置 position: relative,以便叠加层和画布相对于相同的祖先解析位置。如果画布没有已定位的祖先,叠加层将相对于文档解析,<body> 的边距会使其偏离画布。

测试语义

在运行时启用语义后,打开屏幕阅读器并导航你的图形:

  • macOS / iOS:VoiceOver
  • Android:TalkBack
  • Windows:Narrator 或 NVDA

检查每个元素是否播报了清晰的标签、正确的角色、准确的值和状态,以及导航是否遵循逻辑顺序。你也可以在浏览器的开发者工具中检查生成的 DOM——查找紧随画布之后的 <div id="rive-a11y-..."> 元素——或使用浏览器的无障碍树检查器。

完整检查清单请参阅编辑器文档中的测试语义