微信号:FrontDev

介绍:分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯

Canvas 最佳实践(性能篇)

2016-02-23 21:20 前端大全

(点击上方,可快速关注)

作者:淘宝前端团队(FED)- 叶斋 

网址:http://taobaofed.org/blog/2016/02/22/canvas-performance/



Canvas 想必前端同学们都不陌生,它是 HTML5 新增的「画布」元素,允许我们使用 JavaScript 来绘制图形。目前,所有的主流浏览器都支持 Canvas。



Canvas 最常见的用途是渲染动画。渲染动画的基本原理,无非是反复地擦除和重绘。为了动画的流畅,留给我渲染一帧的时间,只有短短的 16ms。在这 16ms 中,我不仅需要处理一些游戏逻辑,计算每个对象的位置、状态,还需要把它们都画出来。如果消耗的时间稍稍多了一些,用户就会感受到「卡顿」。所以,在编写动画(和游戏)的时候,我无时无刻不担忧着动画的性能,唯恐对某个 API 的调用过于频繁,导致渲染的耗时延长。


为此,我做了一些实验,查阅了一些资料,整理了平时使用 Canvas 的若干心得体会,总结出这一片所谓的「最佳实践」。如果你和我有类似的困扰,希望本文对你有一些价值。


本文仅讨论 Canvas 2D 相关问题。


计算与渲染


把动画的一帧渲染出来,需要经过以下步骤:


  1. 计算:处理游戏逻辑,计算每个对象的状态,不涉及 DOM 操作(当然也包含对 Canvas 上下文的操作)。

  2. 渲染:真正把对象绘制出来。

    2.1. JavaScript 调用 DOM API(包括 Canvas API)以进行渲染。

    2.2. 浏览器(通常是另一个渲染线程)把渲染后的结果呈现在屏幕上的过程。



之前曾说过,留给我们渲染每一帧的时间只有 16ms。然而,其实我们所做的只是上述的步骤中的 1 和 2.1,而步骤 2.2 则是浏览器在另一个线程(至少几乎所有现代浏览器是这样的)里完成的。动画流畅的真实前提是,以上所有工作都在 16ms 中完成,所以 JavaScript 层面消耗的时间最好控制在 10ms 以内。

虽然我们知道,通常情况下,渲染比计算的开销大很多(3~4 个量级)。除非我们用到了一些时间复杂度很高的算法(这一点在本文最后一节讨论),计算环节的优化没有必要深究。


我们需要深入研究的,是如何优化渲染的性能。而优化渲染性能的总体思路很简单,归纳为以下几点:


  1. 在每一帧中,尽可能减少调用渲染相关 API 的次数(通常是以计算的复杂化为代价的)。