Fabric.js 画布是一张位图,屏幕阅读器看不到里面的对象。要做好 Fabric.js 编辑器无障碍,关键在画布周围的控件。引擎提供状态,按钮、对话框和状态文字由你的应用渲染。
撤销和重做按钮
<button
onClick={() => engine.undo()}
disabled={!state.canUndo}
aria-keyshortcuts="Control+Z Meta+Z"
>
Undo
{state.undoLabel ? (
<span className="sr-only">: {state.undoLabel}</span>
) : null}
</button>- 用真正的
<button>元素,它们天然支持焦点和键盘操作。 - 把步骤标签,比如「Undo: Move rect」,放进可访问名称里。屏幕阅读器对
title的支持并不可靠。 bindKeyboardShortcuts不会干扰输入框和 Fabric.js 文本编辑,键盘用户在那里仍能使用原生的文本撤销。
保存状态
礼貌地播报保存状态的变化,不要抢走焦点:
<p aria-live="polite" aria-atomic="true">
{state.saveStatus === "saving" && "Saving…"}
{state.saveStatus === "saved" && "All changes saved"}
{state.saveStatus === "unsaved" && "Unsaved changes"}
{state.saveStatus === "error" && "Could not save. Retrying."}
{state.saveStatus === "conflict" && "Someone else changed this document."}
</p>让 aria-live 区域一直留在页面上,只改变它的文字。在变化那一刻才插入的区域,常常不会被播报。
用对话框让用户选择
冲突、恢复提示和缺失的图片都需要用户做决定。把它们放在 <dialog> 里,打开时把焦点移进去,关闭时把焦点还回去。每个选项都要写清楚,比如「保留我的版本」,而不是「确定」。
画布本身
- 给画布一个可访问名称:
<canvas aria-label="Floor plan editor">。 - 用
engine.toDocument().objects生成一份重要对象的文字列表。 - 提供用键盘移动选中对象的方法,比如方向键调用
engine.transaction("Move", ...)。
Fabric.js 编辑器无障碍还意味着不设时间限制。自动保存和恢复都在后台运行,从不要求用户快速响应。