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


---------------------------------------------------------------------
注意:
可能会有人想说把“计算图形”和“擦除”两个步骤对换位置不就解决问题了?看下面绘制五条线条的动画代码你就会知道 , 实际场景中我们编写的代码往往会把“计算图形”和“绘制”混杂在一起 , 使得“擦除”必须在之前执行 。
//五条线的初始化长度var lineHeight=[0,0,0,0,0],tick=16;setTimeout(function animate(){//“擦除”操作还能放在哪里呢?realContext.clearRect(0,0,realCanvas.width,realCanvas.height);for(var i=0;i<5;i++){realContext.moveTo(10*i,10);//使用lineHeight++的方式 , 使得计算图形和绘制混杂在了一起realContext.lineTo(10*i,lineHeight[i]++);}setTimeout(animate,tick);},tick);
---------------------------------------------------------------------
对于如何使用双缓冲绘图机制解决“白屏闪烁”的问题 , 我们同样先展示代码 , 然后通过一张流程图形来详细讲解实现过程:
//初始化元素 , 会创建一个真实画布和虚拟画布var container=document.getElementById("container");var realCanvas=document.createElement("canvas");var cacheCanvas=document.createElement("canvas");realCanvas.width=container.clientWidth*2;realCanvas.height=container.clientHeight*2;cacheCanvas.width=container.clientWidth*2;cacheCanvas.height=container.clientHeight*2;realCanvas.style.width=container.clientWidth+"px";realCanvas.style.height=container.clientHeight+"px";container.appendChild(realCanvas);var realContext=realCanvas.getContext("2d");var cacheContext=cacheCanvas.getContext("2d");/*-------------------初始化完毕--------------------*/var lineHeight=0,tick=16;//第一遍绘制cacheContext.clearRect(0,0,realCanvas.width,realCanvas.height);lineHeight++;cacheContext.moveTo(10,10);cacheContext.lineTo(10,lineHeight);//将cacheCanvas一次性整张画到realCanvas上realContext.drawImage(cacheCanvas,0,0);setTimeout(function animate(){//先在虚拟画布上绘制 , 此时不影响页面cacheContext.clearRect(0,0,realCanvas.width,realCanvas.height);cacheContext++;cacheContext.moveTo(10,10);cacheContext.lineTo(10,lineHeight);//此时重绘页面realContext.clearRect(0,0,realCanvas.width,realCanvas.height);realContext.drawImage(cacheCanvas,0,0);setTimeout(animate,tick);},tick);
流程图如下:

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

文章插图
这一次由于我们将“重新计算坐标点”以及“重新绘制”两个耗时操作移到了虚拟画布上(也就是双缓冲机制) , 而在最后才通过.()的方式一次性将虚拟画布上的图形呈现到页面上(这个操作通常小于1ms) 。通过这种优化手段 , 即使再复杂的图形绘制 , 页面上也不会再看到动画帧之间的白屏问题 , 耗时操作都在虚拟节点上执行 , 真正的画布只会在虚拟画布准备好图形之后才擦除+重绘 。
熬夜不易 , 请作者喝酒!