我们前边提到过,绘制一副较大的图片代价是很高昂的因此我们应尽可能的避免。除了前边讲到的利用另外得不可见的canvas进行预渲染外,我们也可以叠在 一起的多层canvas。图哦你的过利用前景的透明度,我们可以在渲染时依靠GPU整合不同的alpha值。你可以像如下这么设置,两个绝对定位的 canvas一个在另一个的上边:
<canvas id="bg" width="640" height="480" style="position: absolute; z-index: 0">
</canvas>
<canvas id="fg" width="640" height="480" style="position: absolute; z-index: 1">
</canvas>
相对于仅仅有一个canvas的情况来讲,这个方法的优势在于,当我们需要绘制或者清理前景canvas时,我们不需要每次都修改背景 canvas。如果你的游戏或者多媒体应用可以分成前景和背景这样的情况,那么请考虑分贝渲染前景和背景来获取显著的性能提升。下面的图表比较了只有一个 canvas的情况和有前景背景两个canvas而你只需要清理和重绘前景的情况(jsperf):
你可以用相较慢的速度(相对于前景)来渲染背景,这样便可利用人眼的一些视觉特性达到一定程度的立体感,这样会更吸引用户的眼球。比如,你可以在每一帧中渲染前景而仅仅每N帧才渲染背景。
注意,这个方法也可以推广到包含更多canvas曾的复合canvas。如果你的应用利用更多的曾会运行的更好时请利用这种方法。
6.AVOID SHADOWBLUR
跟其他很多绘图环境一样,HTML5 canvas允许开发者对绘图基元使用阴影效果,然而,这项操作是相当耗费资源的。
context.shadowOffsetX = 5;
context.shadowOffsetY = 5;
context.shadowBlur = 4;
context.shadowColor = 'rgba(255, 0, 0, 0.5)';
context.fillRect(20, 20, 150, 100);
下面的测试显示了绘制同一场景使用何不使用阴影效果所带来的显著的性能差异(jsperf):
7.KNOW VARIOUS WAYS TO CLEAR THE CANVAS
因为HTML5 canvas 是一种即时模式(immediate mode)的绘图范式(drawing paradigm),因此场景在每一帧都必需重绘。正因为此,清楚canvas的操作对于 HTML5 应用或者游戏来说有着根本的重要性。
正如在 避免 canvas 状态变化的一节中提到的,清楚整个canvas的操作往往是不可取的。如果你必须这样做的话有两种方法可供选择:调用
context.clearRect(0, 0, width, height)
或者使用 canvas特定的一个技巧
canvas.width = canvas.width
在书写本文的时候,cleaRect方法普遍优越于重置canvas宽度的方法。但是,在某些情况下,在Chrome14中使用重置canvas宽度的技巧要比clearRect方法快很多(jsperf):
请谨慎使用这一技巧,因为它很大程度上依赖于底层的canvas实现,因此很容易发生变化,欲了解更多信息请参见 Simon Sarris 的关于清除画布的文章。
8.AVOID FLOATING POINT COORDINATES
HTML5 canvas 支持子像素渲染(sub-pixel rendering),而且没有办法关闭这一功能。如果你绘制非整数坐标他会自动使用抗锯齿失真以使边缘平滑。以下是相应的视觉效果(参见Seb Lee-Delisle的关于子像素画布性能的文章)
如果平滑的精灵并非您期望的效果,那么使用 Math.floor方法或者Math.round方法将你的浮点坐标转换成整数坐标将大大提高运行速度(jsperf):
为使浮点坐标抓换为整数坐标你可以使用许多聪明的技巧,其中性能最优越的方法莫过于将数值加0.5然后对所得结果进行移位运算以消除小数部分。
// With a bitwise or.
rounded = (0.5 + somenum) | 0;
// A double bitwise not.
rounded = ~~ (0.5 + somenum);
// Finally, a left bitwise shift.
rounded = (0.5 + somenum) << 0;
两种方法性能对比如下(jsperf):
9.OPTIMIZE YOUR ANIMATIONS WITH ‘REQUESTANIMATIONFRAME’
相对较新的 requeatAnimationFrame API是在浏览器中实现交互式应用的推荐标准。与传统的以固定频率命令浏览器进行渲染不同,该方法可以更友善的对待浏览器,它会在浏览器可用的时候使其来 渲染。这样带来的另外一个好处是当页面不可见的时候,它会很聪明的停止渲染。
requestAnimationFrame调用的目标是以60帧每秒的速度来调用,但是他并不能保证做到。所以你要跟踪从上一次调用导线在共花了多长时间。这看起来可能如下所示: