有视觉障碍的用户依靠文本朗读工具(屏幕阅读器)来读取网页上的内容。结构化 HTML 标记使屏幕阅读器能够区分页面、页脚和列表等。无法生成 HTML 标记的应用程序,如基于 canvas 的应用程序,其内容无法被屏幕阅读器识别。
结构良好的 HTML 还使用户能够使用标准的键盘快捷键来导航页面。例如,制表键将把焦点带到页面中的下一个链接,如图 4 所示。
图 4. 用制表键将焦点带到页面中的某个链接甚至 Flash 和 SIlverlight 之类的浏览器插件在提供可访问性方面也迈出了一大步,它们支持通用的键盘快捷键。遗憾的是,canvas 没有为可访问性提供类似的内置兼容。
设备和用户代理最终,由用户代理决定究竟以何种方式呈现您的页面。一些设备对同一 HTML 标记的解释可能不同于其他设备。例如,在大多数移动设备上,单击 <input type="text"> 元素会让设备在屏幕上显示一个键盘,使用户可以输入内容。遵循 HTML5 规范的浏览器提供了更加广泛的可用输入类型,如电子邮件、网站、电话和日期等。
图 5 显示了 <input type="date"> 元素如何显示在 iOS 设备上。浏览器自动显示一个全功能日期选择器;实现该日期选择器不需要任何额外的代码,只需将输入元素的类型定义为 date。
图 5. iPhone 对 <input type="date"> 的处理在编写语义正确的 HTML 时,您实际上是对用户代理签订了一个协议,认为该用户代理能够以最适合该设备用户的方式呈现内容。
相比之下,canvas 元素中呈现的内容在所有设备上都始终如一。您将打破与用户代理的契约;认为设备并不知道如何以最佳方式呈现内容。
超链接感知实际上,Web 是围绕超链接构建的,无法想象没有超链接的世界会是什么样。除了允许用户导航链接外,现代用户代理为用户提供了丰富的上下文特性:在新的选项卡中打开页面、复制链接地址和电子邮件链接等。
尽管文本可以呈现到 canvas 中,从理论上讲,并不存在超链接的概念。
即使您自己动手模拟一个超链接,呈现蓝色的带下划线的文本,用户代理仍然不会认为这是一个真正的超链接,因此无法向用户提供任何有用的上下文功能。
canvas API 的优点了解了 HTML 的长处后,专为 canvas 编写的应用程序似乎一无所长。然而,围绕 canvas 构建解决方案也有一些优势。最主要的优势是 canvas 具有较高的图形性能,可实现跨设备的一致性。
图形性能有一些任务使用 HTML 和 canvas 均能够完成,如呈现图像、文本和动画。
由于 canvas 不存在与解析 HTML 和维护分层文档模型有关的开销,因此,在 canvas 中这些任务总是要比在 HTML 中快。
在以 HTML 为中心的应用程序中,最消耗性能的因素就是添加、移除或更新节点。更新文档模型通常要求浏览器重现展示整个页面,这一个涉及大量计算的过程。在实时应用程序中需要每秒对文档模型进行多次更新,只会减缓浏览器的速度。
对于十分看重速度的场景,从以 HTML 为中心的架构切换到以 canvas 为中心的架构是实现最大性能的最佳方式。实现高性能的代价就是要处理低级 API,而非 HTML 等健壮的标记语言以及 CSS 的灵活性。
跨设备一致性实现一致的、跨平台的呈现对于传统的 HTML/CSS 模型一直是个难题,因为浏览器布局引擎不一样。尽管可以跨平台实现极为相近的网页,但是很难在 “像素级别” 实现一致的设计。
当在 canvas 上绘制图形时,这些问题就迎刃而解。Canvas 支持对图形和文本的呈现进行像素级控制,并且保证输出在所有平台上都 100% 一致。
混合使用 canvas/HTML 的基本原理在创建面向 canvas 的应用程序时,传统 HTML/CSS 模型的特性也可用于弥补 canvas 的短处。
如前所述,canvas 的一大弊端就是难以实现健壮的、可访问的 UI 组件。在确定实现 UI 的最佳方法时,评估 UI 元素的需求是一种很好的实践。需要考虑的评判标准包括:
以上任意方面提出的需求都会对实现方式有很大影响。例如,如果所需的内容是以文本方式显示应用程序的某个方面,那么使用最基本的 HTML 元素将是最有效的方法,并且不会引起任何性能损失。然而,如果您希望元素具有动态效果,或富有频繁更新的内容,那么使用 canvas 可能更理想。如果要求具备易于交互的特性,那么 HTML 元素通常提供最自然的方法,特别是当结合使用 jQuery 等库提供的功能时。
接下来,我们将演示一些非常适合使用 canvas/HTML 混合实现的场景。
快速原型化使用 HTML 和 CSS 实现快速原型化要比使用 canvas 快得多。例如,考虑一个包含菜单的应用程序。因为菜单非常适合 HTML/CSS 结构,并且您可以利用大量现有的库,如 jQuery 插件,因此与在 canvas 中的实现相比,在 HTML 中实现菜单所需的工作量非常小。对于原型化来说,HTML 引起的性能减退并不是什么大问题,因为使用它的目的是实现概念证明而不是一个完全优化的系统。
当应用程序实现增强后,原型化中采用 HTML 和 CSS 的部分未来可能会完全使用纯 canvas 实现。在菜单例子中,在最终产品中将菜单变为 canvas 将极大地改善性能,因为您去掉了对浏览器文档模型的依赖。
开发工具开发工具可以很轻松地应用于 HTML 和 CSS,因为使用 HTML 标记可以很方便地显示大量的信息。一个例子就是在应用程序中添加控制台来实现调试的目的。调试控制台会显示统计数据,比如每秒帧数,应用程序中所有对象的列表以及它们的坐标等。
再次重申,在这种场景下引入 HTML 元素所造成的性能损失并不是什么大问题,因为这些工具只面向开发人员,并且永远也不会显示给最终用户。
用户界面覆盖如果应用程序需要一个富 UI 来汇合来自不同元素的文本,如复选框和下拉菜单,那么 HTML 是最自然不过的选择。在 canvas 中重现这些类型的组件将耗费大量的时间,并且您的应用程序很可能会出现访问性问题。
相反,HTML 的优点可以提供丰富的用户体验。例如,基于 HTML 的 UI 组件的集合可以包含一个漂浮在 canvas 区域上的 “提醒 (heads up) 显示”。
为了最大程度减小对应用程序实时性能的影响,要注意尽可能少地对文档模型进行修改(元素更新、插入和移除)。如果文档更新非常频繁,那么应用程序的性能可能会非常慢。
伙伴用户界面如果意图将某个 UI 元素显示在应用程序的交互式实时组件以外,那么此时十分适合使用 HTML 和 CSS。例如,UI 元素可能仅在开始启动顺序或应用程序暂停时出现。
加载/保存游戏界面是另一个可以利用基于 HTML 的伙伴用户界面示例。因为用户在保存游戏时将暂停游戏,因此不会对应用程序的实时性能产生影响。HTML/CSS 允许快速开发该界面,并利用了组织良好的标记的优点。
实现 canvas/HTML 混合模型