canvas的效能優化(快取問題)
阿新 • • 發佈:2019-02-01
使用快取
使用快取就是用離屏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<this.r;i+=borderWidth){
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;j<num;j++){
this.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.r;i+=borderWidth){
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);