HTML5-canvas绘图黑屏白屏解决方案(详解双缓冲绘图机制)
使用canvas绘图的前端工程师可能都会遇到过canvas绘图黑屏、白屏的问题。以前写过一篇文章描述过hybrid下canvas黑屏的一种可能性:
http://blog.youkuaiyun.com/yuhk231/article/details/53560782
那么如果我们面对的场景就是移动端各大浏览器呢?当出现黑屏、白屏的时候就只能认栽了吗?不是的,还有很多优化工作是我们可以做的。在这里本文就将详细分析绘图策略中最伟大的方法:双缓冲绘图机制。
百度百科搜索双缓冲技术绘图,解释如下:双缓冲即在内存中创建一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度。拿html5-canvas场景来举例:就是我们创建两个相同的画布,一张画来打草稿(在内存中的canvas虚拟节点上绘制),一张真正画给观众看(真正的页面dom元素canvas绘制)。
介绍完了背景知识,那这种技术到底能做什么?说了那么多和本文的主题解决黑屏白屏问题又有什么关联?
·黑屏
先来讨论黑屏的情况。我们知道,移动设备上canvas呈现出黑屏很大一部分原因就是绘图的计算量太大,导致设备显示出现问题。那么最直接的解决方案就是减少计算量(或者称为优化)。
正常情况下,我们会为页面添加一个canvas元素,并且一边算各种图形坐标,一边一点点的绘制上去。在这个过程当中我们就损耗了相当大的性能,每执行一次context.fill()或者context.stroke(),图形都会被渲染一次。而利用双缓冲机制,我们这样处理:为页面添加一个canvas元素,同时创建另一个一个一模一样的canvas元素,但是不添加到页面dom树(也就是存在内存中),这时我们在内存中的canvas元素上一边算图形坐标一边绘制,当绘制完成时直接调用canvas的复制方法(context.drawImage)一次性将“草稿画布”上的图形绘制到真正的页面canvas元素上,通过这样的技巧,我们将会节省大量页面绘制的性能损耗,不但能解决黑屏的问题,还能缩短图形绘制的时间。这里有一篇可以说明虚拟画布和普通画布差异的文章:
http://blog.youkuaiyun.com/yuhk231/article/details/54376525
下面我们来描述一下javascript如何实现上文所述的双缓冲机制。
先来看一段很普通的绘制一个正方形的代码:
//获取页面中的canvas画布容器,通常为一个div
var container=document.getElementById("container");
//创建一个真实的画布,他将呈现给用户
var realCanvas=document.createElement("canvas");
//设置realCanvas的width/height属性,乘以二以防止像素点模糊问题
realCanvas.width=container.clientWidth*2;
realCanvas.height=container.clientHeight*2;
//设置realCanvas