-
Notifications
You must be signed in to change notification settings - Fork 31
Description
前段时间学了点canvas,写了些代码。发现自己写的代码有些动画运行的时候会有卡顿,闪烁,掉帧这些现象,应该是我太菜了,所以上网找了找解决办法。然后发现了一篇文章,里面总结了一些提高canvas性能的方法,还是比较全面的,所以拿过来和大家分享。
原文地址:
如果你对canvas不了解或没兴趣不想看原文,那我下面就把文章中的方法简单提一下。希望对你在运用其他平台做动画的时候能有所启示。
1.预渲染
先把图像渲染在一个不可见的canvas上,再把不可见的canvas渲染到可见的canvas上。
2.用一个长的指令集载入将绘图状态机载入,然后再一次性的全部写入到video缓冲区。
例如,当需要画多条线时先创建一条包含所有线条的路经然后用一个draw调用将比分别单独地画每一条线条要高效的多。
3.减少操纵状态机
例如:为了渲染一副条纹的图案,你可以这样渲染:用一种颜色渲染一条线条,然后改变颜色,渲染下一条线条,如此反复;也可以先用一种颜色渲染所有的偶数线条再用另外一种染色渲染所有的奇数线条,而第一种方法会慢得多。
(总之减少调用canvasAPI)
4.尽量避免全屏重绘
重绘时如果只有少量的差异你可以通过仅仅重绘差异部分来获得显著的性能提升。
5.用叠在一起的多个canvas绘制
6.减少阴影效果
因为阴影效果相当耗费资源
7.用不同的方法清理canvas
原文中提到clearRect()和重置画布宽度两种方法,不过我查过之后发现重置画布宽度是为了避免不同的方法都调用同一个canvas时,只调用clearRect()之后,再次绘制会的出现偏移现象。不知道是什么意思。。。希望大神解释
8.避免浮点坐标
用Math.floor或者Math.round把浮点坐标转化成整数坐标。文中还提供了一个转化坐标的办法。
9.运用requestAnimationFrame API
据说这个才是动画的最佳循环,而不是setTimeout或setInterval。
最后,这篇文章很老了,可能有些方法不能用了。。。
我在上网查找怎么优化canvas性能的时候,有人说用双缓冲(一听就高大上是不是)来解决闪烁问题。原文是这么说的”创建一个临时canvas,先把下一帧动画绘制到临时canvas上。在每次真正绘制的时候,擦除正式canvas后,用drawImage把临时canvas的内容copy过去,而这个copy过程是非常非常高效的,所以基本可以杜绝闪烁。”是不是看起来很眼熟。。。跟上面的预渲染很像。。。后来,又发现一篇文章,作者表示canvas没有双缓冲这种东东。。。原文:”使用缓存也就是用离屏canvas进行预渲染了,原理很简单,就是先绘制到一个离屏canvas中,然后再通过drawImage把离屏canvas画到主canvas中。可能看到这很多人就会误解,这不是写游戏里面用的很多的双缓冲机制么?其实不然,双缓冲机制是游戏编程中为了防止画面闪烁,因此会有一个显示在用户面前的画布以及一个后台画布,进行绘制时会先将画面内容绘制到后台画布中,再将后台画布里的数据绘制到前台画布中。这就是双缓冲,但是canvas中是没有双缓冲的,因为现代浏览器基本上都是内置了双缓冲机制。所以,使用离屏canvas并不是双缓冲,而是把离屏canvas当成一个缓存区。把需要重复绘制的画面数据进行缓存起来,减少调用canvas的API的消耗。”好了,我也懵了。。。希望大神解释一下。不过可能名字不同,方法还是那样,凑合着用吧。
其实写一些小游戏的话,canvas还是挺好用的。有什么不足之处希望大神补充。