Canvas 与 双缓冲 相关文章

来源:互联网 发布:淘宝店铺音乐代码 编辑:程序博客网 时间:2024/06/14 18:29
作者:严天宇
链接:http://www.zhihu.com/question/25036663/answer/29881637
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

对于CANVAS绘制性能提高问题,可以考虑使用“双缓冲”技巧。
CANVAS图像传统绘制是这个样子的:

(1)在可见画布上画出一个圆。

(2)在可见画布上画出一个三角。

(3)在可见画布上画出一个方块。

“双缓冲”技巧则是这个样子:

(1)在非可见画布上画出一个圆。

(2)在非可见画布上画出一个三角。

(3)在非可见画布上画出一个方块。

(4)将非可见画布上的内容一次性画到可见画布上。

也就是说,在浏览器上,使用双缓冲技术进行canvas对象的绘制只会对浏览器进行一次渲染。就理论而言,在需要绘制的东西非常多的时候,双缓冲技术可以有效减少页面闪烁次数。


之前做过实验,在canvas画布中有若干个圆做无规则碰撞运动,设定两个对照组,一个用传统方法绘制圆,另一个则是使用双缓冲技巧。以下是实验记录:

第一次对比:

两组都是900个圆在CANVAS中进行无规则运动并相互碰撞,两组都运行流畅

第二次对比:

两组都是1100个圆在CANVAS中进行无规则运动并相互碰撞,两组都运行流畅

第四次对比:

两组都是2100个圆在CANVAS中进行无规则运动并相互碰撞,两组都开始出现掉帧现象

第五次对比:

两组都是2500个圆在CANVAS中进行无规则运动并相互碰撞,两组都有较为明显的卡顿现象,仍然没有明显的性能差别

第六次对比:

两组都是3000个圆在CANVAS中进行无规则运动并相互碰撞,两组都卡顿,仍然没有明显的性能差别

第七次对比:

两组都是3500个圆在CANVAS中进行无规则运动并相互碰撞,两组都很卡顿,仍然没有明显的性能差别<img src="https://pic3.zhimg.com/d539c9a3f06b57a895845f562c7e35ce_b.jpg" data-rawwidth="1365" data-rawheight="733" class="origin_image zh-lightbox-thumb" width="1365" data-original="https://pic3.zhimg.com/d539c9a3f06b57a895845f562c7e35ce_r.jpg">


当时的出的结论是:双缓冲技巧对于HTML5 CANVAS性能提升效果并不明显。


现在想来,其实还有一种可能:浏览器把性能都用在计算那几千个撞来撞去的圆的速度、角度变化上去了,而“大量绘制图像”的实验目的并没有得到体现。

另外,所谓“卡顿程度”在当时是使用肉眼判断的,这又是另一个不严谨之处。


在开发 图像 动画 游戏 相关的程序时, 双缓冲( double-buffer )一直是程序员常用(必用)的技巧. 
当然 随着各种引擎 框架的发展,以及计算机语言本身的进步 开发人员已经不需要在亲自去实现了(其实 这个实现起来也不复杂) 


HTML5中的canvas 为我们使用js在浏览器中进行图形图像以及动画游戏的开发提供了基础保障, 但是它并没有高级到会自动的实现双缓冲, 不过不用担心, 因为它根本不需要双缓冲. 

双缓冲最初的本意 是为了减少可见屏幕(画布)的刷新次数 避免画面闪烁. 

在传统语言中 如果不使用双缓冲,执行下面的操作: 

1 在可见画布上画出一个圆  //系统自动刷新并渲染可见画布 
2 在可见画布上画出一个三角 //系统自动刷新并渲染可见画布 
3 在可见画布上画出一个方块 //系统自动刷新并渲染可见画布 

那么每一步之后 显示系统都会刷新一次"可见画布", 也就是说在短短的时间里 会刷新多次画布. 

使用双缓存之后(多了一个非可见画布,也就是那个缓冲): 

1 在非可见画布上画出一个圆 
2 在非可见画布上画出一个三角 
3 在非可见画布上画出一个方块 
4 将非可见画布上的内容一次性画到可见画布上 

使用双缓冲后 虽然绘画次数多了一次, 但是 实际上可见画布的刷新次数变少了 可以有效的降低画面闪烁的现象. 


而在浏览器中使用canvas时, 没必要使用双缓冲, 因为系统不会在每次绘图之后都立即刷新canvas. 

举个例子 伪代码. 

function a(){ 
  for (var i=0;i<10;i++){ 
    // 在canvas上画一些东西 
  } 


当执行函数a时, 虽然对canvas执行了10次的绘图操作,但是并不会刷新和渲染可见画布,而只有当函数执行完成后 才会一次性的刷新并渲染出canvas上的东西. 
(当然 如果你使用了setTimeout那就另当别论了) 

网上有一些人用canvas写的游戏 自己实现了一套双缓冲机制, 其实完全多余的,对性能不仅没有提高 还会有一定的降低. 

================================= 

以上结论只针对 2010年3月23日之前的 canvas和js,  以后如果js 浏览器 canvas有什么变化 我不敢保证. 

不过 即使以后js支持多线程了 支持更多NB特性了, 那么我觉得这个双缓冲也是多余的. 
这个本来就应该是机器底层 操作系统甚至是硬件级别支持的, 顶层编码人员原本就不应该去关注所谓的双缓冲. 

================================= 

0 0
原创粉丝点击