HTML5-canvas绘图黑屏白屏解决方案(详解双缓冲绘图机制)

2017-01-13 08:23:45来源:CSDN作者:yuhk231人点击

HTML5-canvas绘图黑屏白屏解决方案(详解双缓冲绘图机制)

使用canvas绘图的前端工程师可能都会遇到过canvas绘图黑屏、白屏的问题。以前写过一篇文章描述过hybrid下canvas黑屏的一种可能性:

http://blog.csdn.net/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.csdn.net/yuhk231/article/details/54376525

下面我们来描述一下javascript如何实现上文所述的双缓冲机制。

先来看一段很普通的绘制一个正方形的代码:
//获取页面中的canvas画布容器,通常为一个divvar container=document.getElementById("container");//创建一个真实的画布,他将呈现给用户var realCanvas=document.createElement("canvas");//设置realCanvas的width/height属性,乘以二以防止像素点模糊问题realCanvas.width=container.clientWidth*2;realCanvas.height=container.clientHeight*2;//设置realCanvas的样式width/height属性,填充满父元素realCanvas.style.width=container.clientWidth+"px";realCanvas.style.height=container.clientHeight+"px";container.appendChild(realCanvas);//开始绘制var realContext=realCanvas.getContext("2d");realContext.fillRect(0,0,100,100);

下面一段代码与前面的代码功能完全相同,但是实现时使用了双缓冲绘图机制:

//获取页面中的canvas画布容器,通常为一个divvar container=document.getElementById("container");//创建一个真实的画布,他将呈现给用户var realCanvas=document.createElement("canvas");//设置realCanvas的width/height属性,乘以二以防止像素点模糊问题realCanvas.width=container.clientWidth*2;realCanvas.height=container.clientHeight*2;//设置realCanvas的样式width/height属性,填充满父元素realCanvas.style.width=container.clientWidth+"px";realCanvas.style.height=container.clientHeight+"px";container.appendChild(realCanvas);//创建一个虚拟节点cacheCanvas,我们不会将他添加到页面上var cacheCanvas=document.createElement("canvas");//设置cacheCanvas的width/height属性,和realCanvas的完全相同cacheCanvas.width=container.clientWidth*2;cacheCanvas.height=container.clientHeight*2;//开始绘制,获取真实节点和虚拟节点的上下文contextvar realContext=realCanvas.getContext("2d");var cacheContext=cacheCanvas.getContext("2d");/* * 这次试用双缓冲技术,我们在cacheCanvas中绘制, * 但此时什么都看不到,因为cacheCanvas没有添加到页面上 */cacheContext.fillRect(0,0,100,100);/* * 在缓冲区完成绘制之后,我们将缓冲区的内容一次性绘制到页面上 */realContext.drawImage(cacheCanvas,0,0);

经过了这样的优化之后,一般的图形都不会在出现HTML5-canvas黑屏的现象了。

·白屏

说完了黑屏,接下来说说白屏。

先简单阐述一下为什么会产生白屏。首先可以肯定的是:白屏一定是程序有问题!最常见的情况:

(1)绘图代码报错,导致绘图不执行,因此出现白屏

(2)计算图形坐标的时候算错,比如计算出无穷大或者undefined或者超出画布边界的坐标值,导致你画的图看不见(HTML5-canvasAPI在执行绘图方法时传入的数据异常时不会抛出任何错误),也是白屏。

(3)没有给画布canvas设置width或height或值为0,比如画布初始化的时候页面还没有撑开,导致画布canvas元素的高度或者宽度为零,也会出现白屏。

(4)如果看到这里仍然没有解决你的白屏问题,那么恭喜你,本文将帮助你解决“canvas动画白屏闪烁”问题。

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台