对一个矢量图动画,开启位图缓存能大大提高运行效率。所谓开启位图缓存,其实要自己动手,先创建一个临时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