canvas的性能优化(缓存问题)

文章原创来源于:http://www.cnblogs.com/axes/p/3567364.html?utm_source=tuicool&utm_medium=referral

使用缓存

使用缓存就是用离屏canvas进行预渲染了。原理就是先绘制一个离屏canvas,然后再通过drawImage把离屏canvas画到主canvas中。把离屏canvas当成一个缓存区,需要重复绘制的画面数据进行缓存。减少调用canvas的API消耗。
例如下面的DEMO:

1、使用了缓存
2、没使用缓存
看到上面的DEMO性能明显不一样。分析一下原因:为了实现每个圈的样式,所以绘制圈圈时用了循环绘制,如果没有启用缓存,当页面的圈圈数量达到一定时,动画的每一帧就要大量调用canvas的API,要进行大量的计算,这样再好的浏览器也会被拖垮。

ctx.save();
var j=0;
ctx.lineWidth = borderWidth;
for(var i=1;i
  ctx.beginPath();
  ctx.strokeStyle = this.color[j];
  ctx.arc(this.x , this.y , i , 0 , 2*Math.PI);
  ctx.stroke();
  j++;
}
ctx.restore();

除了创建离屏的canvas作为缓存之外,下面的代码中有一点很关键,就是要设置离屏canvas的宽度和高度,canvas生成后的默认大小是300X150,对于代码中每个缓存起来圈圈对象半径最大也就不超过80,所以300X150的大小明显会造成很多空白区域,会造成资源浪费,所以要设置一下离屏canvas的宽度和高度,让他跟缓存起来的元素大小一致,这样有利于提高动画性能。

var ball = function(x , y , vx , vy , useCache){
                this.x = x;
                this.y = y;
                this.vx = vx;
                this.vy = vy;
                this.r = getZ(getRandom(20,40));
                this.color = [];
                this.cacheCanvas = document.createElement("canvas");
                this.cacheCtx = this.cacheCanvas.getContext("2d");
                this.cacheCanvas.width = 2*this.r;
                this.cacheCanvas.height = 2*this.r;
                var num = getZ(this.r/borderWidth);
                for(var j=0;jthis.color.push("rgba("+getZ(getRandom(0,255))+","+getZ(getRandom(0,255))+","+getZ(getRandom(0,255))+",1)");
                }
                this.useCache = useCache;
                if(useCache){
                    this.cache();
                }
            }

当实例化圈圈对象时,直接调用缓存方法,把复杂的圈圈直接画到圈圈对象的离屏canvas中保存起来。

cache:function(){
                    this.cacheCtx.save();
                    var j=0;
                    this.cacheCtx.lineWidth = borderWidth;
                    for(var i=1;i
                        this.cacheCtx.beginPath();
                        this.cacheCtx.strokeStyle = this.color[j];
                        this.cacheCtx.arc(this.r , this.r , i , 0 , 2*Math.PI);
                        this.cacheCtx.stroke();
                        j++;
                    }
                    this.cacheCtx.restore();
                }

然后在接下来的动画中,只需要把圈圈对象的离屏canvas画到主canvas中,这样,每一帧调用的canvasAPI就只有这么一句话:
ctx.drawImage(this.cacheCanvas , this.x-this.r , this.y-this.r);

你可能感兴趣的:(canvas)