我正在尝试使用 p5 js 库制作游戏,我希望用户能够使用选项卡按钮进入画布。
我尝试添加 tabindex = "0" 但这不起作用。我可以使用选项卡浏览导航链接,但画布未突出显示。如果有人能指出我正确的方向,那就太好了!
很高兴您考虑将键盘辅助功能作为项目的一部分。
不幸的是,没有简单的技巧来获得可通过键盘访问、屏幕阅读器友好的
<canvas>
元素。事实上,这需要大量的代码和规划。
一般来说,避免对任何可以在网页文档结构中表示的内容使用
<canvas>
。最好留给 2D 或 3D 游戏,这些游戏具有独特的输入机制,而且往往会忽略残障用户。
<canvas>
HTML 元素支持 HTML 后代,浏览器将其转换为可访问(不可见)的 DOM 节点。
基本上,您应该将画布像素数据重新创建为嵌套在
<canvas>
HTML 元素内的不可见 DOM 结构。该结构内的交互元素可以接收键盘焦点。
将
click
处理程序添加到不可见的交互元素(例如 <a>
和 <button>
),这些元素映射到键盘激活键(Enter 键和按钮情况下的空格键)。激活不可见元素应执行与用户用鼠标单击画布的相应可视区域相同的操作。
还可以考虑添加相同的文本、表格以及画布区域中以像素表示的任何其他内容作为嵌套的不可见 DOM。这将有助于屏幕阅读器用户,他们可以导航非交互式结构。
但您的问题更多的是关于使用键盘的视力正常的用户的视觉反馈。这意味着手动为每个交互式不可见 DOM 元素添加焦点环轮廓。
这可能很棘手,因为您可能需要更新画布像素数据以相应地绘制轮廓。
或者,这可以在支持 CSS :has()
选择器的
现代浏览器中使用 DOM 来实现。
在这种情况下,您将为每个交互元素创建一个匹配的
<div>
。每个都将被放置在一个容器 <div>
中,该容器紧跟在 HTML 中的 <canvas>
之后,该容器位于画布顶部。
您绝对会定位每个匹配的
<div>
元素,以便它们出现在与画布中各自的视觉区域相同的坐标处。
然后,使用一些相当复杂的 CSS 选择器,您可以触发匹配的
<div>
在嵌套的不可见元素获得焦点时显示焦点环轮廓。
这是我测试的解决方案:
<style>
.canvas__container {
display: flex;
position: relative;
width: fit-content;
}
.canvas__outlines {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.canvas__outline {
position: absolute;
border: 2px solid transparent;
}
.nav__link--about__outline {
top: 20px;
left: 20px;
width: 180px;
height: 50px;
}
.nav__link--products__outline {
top: 20px;
left: 220px;
width: 200px;
height: 50px;
}
.nav__link--contact__outline {
top: 20px;
left: 440px;
width: 190px;
height: 50px;
}
.canvas:has(.nav__link--about:focus-within)
+ .canvas__outlines
.nav__link--about__outline,
.canvas:has(.nav__link--products:focus-within)
+ .canvas__outlines
.nav__link--products__outline,
.canvas:has(.nav__link--contact:focus-within)
+ .canvas__outlines
.nav__link--contact__outline {
border-color: Highlight;
}
</style>
<div class="canvas__container">
<canvas class="canvas" height="500" width="500">
<nav>
<a href="/about" class="nav__link--about">About </a>
<a href="/products" class="nav__link--products">Products</a>
<a href="/contact" class="nav__link--contact">Contact</a>
</nav>
</canvas>
<div class="canvas__outlines">
<div class="canvas__outline nav__link--about__outline"></div>
<div class="canvas__outline nav__link--products__outline"></div>
<div class="canvas__outline nav__link--contact__outline"></div>
</div>
</div>