對一個矢量圖動畫,開啟位圖緩存能大大提高運行效率。所謂開啟位圖緩存,其實要自己動手,先創建一個臨時canvas,然后把矢量圖繪制到這個canvas上,到了實際繪制時,直接把這個臨時canvas拷貝到真正canvas上。而位圖拷貝的速度是非常快的,比重新繪制矢量圖要快很多。
三部曲:
1、建立臨時canvas(位圖緩存)
p.cache = function(x, y, width, height, scale) { // draw to canvas. scale = scale||1; if (!this.cacheCanvas) { this.cacheCanvas = document.createElement("canvas");} this._cacheWidth = width; this._cacheHeight = height; this._cacheOffsetX = x; this._cacheOffsetY = y; this._cacheScale = scale; this.updateCache(); }
2、繪制到臨時canvas
p.updateCache = function(compositeOperation) { var cacheCanvas = this.cacheCanvas, scale = this._cacheScale, offX = this._cacheOffsetX*scale, offY = this._cacheOffsetY*scale; var w = this._cacheWidth, h = this._cacheHeight, fBounds; if (!cacheCanvas) return; var ctx = cacheCanvas.getContext("2d"); w = Math.ceil(w*scale); h = Math.ceil(h*scale); if (w != cacheCanvas.width || h != cacheCanvas.height) { cacheCanvas.width = w; cacheCanvas.height = h; } else if (!compositeOperation) { ctx.clearRect(0, 0, w+1, h+1); } ctx.save(); ctx.globalCompositeOperation = compositeOperation; ctx.setTransform(scale, 0, 0, scale, -offX, -offY); this.draw(ctx, true); this._applyFilters(); ctx.restore(); };
3、copy到真正canvas
p.drawFromCache = function(ctx) { var cacheCanvas = this.cacheCanvas; if (!cacheCanvas) { return false; } var scale = this._cacheScale, offX = this._cacheOffsetX, offY = this._cacheOffsetY, fBounds; if (fBounds = this._applyFilterBounds(offX, offY, 0, 0)) { offX = fBounds.x; offY = fBounds.y; } ctx.drawImage(cacheCanvas, offX, offY, cacheCanvas.width/scale, cacheCanvas.height/scale); return true; };
但是,這樣會引起問題。在Android上運行,可以發現webview native層的內存占用飛漲,關鍵因素就是這個位圖緩存。
雖然矢量圖可能在舞台上被移除了,但由於JS層和DOM層兩個關聯,導致垃圾回收機制沒有正常發揮。
需要注意的是,在矢量圖被移除的時候,必須在JS側顯式地把臨時canvas置為null
