简介
HTML5 canvas 最初起源于苹果(Apple)的一项实验,现在已经成为了web中受到广泛支持的2D快速模式绘图(2Dimmediate mode graphic)的标准。许多开发者现在利用它来实现众多的多媒体项目、可视化醒目以及游戏等等。然而,随着我们构建的应用程序的复杂度的增加,我们难免会遇到所谓的性能问题。
已经存在众多优化canvas性能的方法了,但是还没有一篇文章将这些方法系统的整理并加以分析。本文的目的就在于将这些方法整理、巩固以使其曾为 开发者们更容易理解、消化、吸收的资源。本文囊括了适用于所有计算机绘图环境(computer graphics environments)的最基本的优化方法,以及特定于canvas的优化方法。其中特定于canvas的优化方法可能会随着canvas实现方式的 更新而发生变化。特别的,当浏览器开发商实现了canvas GPU 加速时,我们探讨的某些优化方法可能会显得并不是特别有效,这些情况我们会在特定的地方标注出来。
请注意,本文侧重点不在于讨论HTML5 canvas的用法。如果想了解canvas的具体用法可以参见HTML5 Rocks网站中canvas相关的文章。比如Dive into HTML5 chapter 以及MDN tutorial。
性能测试
为了处理飞速变化着的HTML5 canvas,JSPerf(jsperf.com) 测试证明了我们在文中提到的每一个方法目前都还生效。JSPerf是一个十分有用的web应用程序,web开发者们可以利用此程序编写 JavaScript 性能测试用例。每一个测试用例只关注你企图达到的某一方面的结果(比如说清楚画布),每一个这样的测试用例包含有若干个能够达到同一结果的不同方法。 JSPerf在一小段时间内尽可能多的运行每一个方法,并没给出一个统计学上有显著意义的每秒中迭代次数。高分意味着更高的性能。
浏览者可以在自己的浏览器中打开JSPerf 性能测试页面,而且可以让JSPerf把标准化的测试结果存储在Browserscope(broserscope.org)中。因为本文中提到的优化技术已经备份到了JSPerf的结果中,因此你可以重新运行查看最新的信息以确定相应的方法是否还有效。我已经写了一个小的帮助应用程序(helpe applicatin)来将测试的结果绘制成图表嵌入到整篇文章中。
本文中的性能测试结果与特定的浏览器版本有很重要的关系。由于我们不知到您用的浏览器运行在什么操作系统上,更重要的是也不知道在您进行这些测试时 HTML5 canvas是否被硬件加速。你可以在Chrome浏览器地址栏中使用 about:gpu 命令来查看Chrome的HTML5 canvas 是否被硬件加速。
1.PRE-RENDER TO AN OFF-SCREEN CANVAS
我们在写一个游戏的时候常常会遇到在多个连续的帧中重绘相似的物体的情况。在这中情况下,你可以通过预渲染场景中的大部分物体来获取巨大的性能提 升。预渲染即在一个或者多个临时的不会在屏幕上显示的canvas中渲染临时的图像,然后再把这些不可见的canvas作为图像渲染到可见的canvas 中。对于计算机图形学比较熟悉的朋友应该都知道,这个技术也被称做display list。
例如,假定你在重绘以每秒60帧运行的Mario。你既可以在每一帧重绘他的帽子、胡子和“M”也可以在运行动画前预渲染Mario。
2.BATCH CANVAS CALLS TOGETHER
因为绘图是一个代价昂贵的操作,因此,用一个长的指令集载入将绘图状态机载入,然后再一股脑的全部写入到video缓冲区。这样会会更佳有效率。
例如,当需要画对条线条时先创建一条包含所有线条的路经然后用一个draw调用将比分别单独的画每一条线条要高效的多。
3.AVOID UNNECESSARY CANVAS STATE CHANGES
HTML5 canvas元素是在一个状态机之上实现的。状态机可以跟踪诸如fill、stroke-style以及组成当前路径的previous points等等。在试图优化绘图性能时,我们往往将注意力只放在图形渲染上。实际上,操纵状态机也会导致性能上的开销。
例如,如果你使用多种填充色来渲染一个场景,按照不同的颜色分别渲染要比通过canvas上的布局来进行渲染要更加节省资源。为了渲染一副条纹的图案,你可以这样渲染:用一种颜色渲染一条线条,然后改变颜色,渲染下一条线条,如此反复。
4.RENDER SCREEN DIFFERENCES ONLY, NOT THE WHOLE NEW STATE
这个很容易理解,在屏幕上绘制较少的东西要比绘制大量的东西节省资源。重绘时如果只有少量的差异你可以通过仅仅重绘差异部分来获得显著的性能提升。换句话说,不要在重绘前清除整个画布。
5.USE MUTIPLE LAYERED CANVASES FOR COMPLEX SCENES
我们前边提到过,绘制一副较大的图片代价是很高昂的因此我们应尽可能的避免。除了前边讲到的利用另外得不可见的canvas进行预渲染外,我们也可以叠在 一起的多层canvas。图哦你的过利用前景的透明度,我们可以在渲染时依靠GPU整合不同的alpha值。你可以像如下这么设置,两个绝对定位的 canvas一个在另一个的上边。
............................................