Canvas动画 位图缓存提高效率和对应的内存问题

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Windows Community

Windows Community Toolkit 3.0 - UniformGrid

UniformGrid 控件是一个响应式的布局控件,允许把 items 排列在一组均匀分布的行或列中,以填充整体的可用显示空间,形成均匀的多个网格。默认情况下,...

832
来自专栏更流畅、简洁的软件开发方式

发布一个锁定行列的一种方法。(实现Excel里的冻结窗格的功能)

功能介绍:     可以实现锁定表格的行和列的功能,效果和Excel里的冻结窗格类似,当然没有Excel那么强大了,只是类似。 问题:     当一个t...

2976
来自专栏GIS讲堂

jquery判断一个div的边界是否超出另外一个div的边界

摘要:本文简单介绍jquery判断一个div的边界是否超出另外一个div的边界,如果超出边界做出相应的处理。

714
来自专栏菩提树下的杨过

ExtJs学习笔记(11)_Absolute布局和Accordion布局

ExtJs其实在某种程度上可以代替div+css来进行页面布局(不过经测试,在最新的Firefox3下,部分功能好象有点问题),今天我们来学习二种最基本的布局 ...

1676
来自专栏阿炬.NET

FineUIMvc表格数据库分页,使用CYQ.Data组件

4038
来自专栏菩提树下的杨过

fms4 p2p:图片分享

这其实是http://www.flashrealtime.com/file-share-object-replication-flash-p2p/ 中关于文件分...

1837
来自专栏AhDung

【C#】分享一个可灵活设置边框的Panel

---------------------------更新:2014-05-19---------------------------

701
来自专栏阿炬.NET

FineUIMvc表格数据库分页,使用CYQ.Data组件

1064
来自专栏C/C++基础

C#子窗体精确定位到父窗体的某个位…

弹出的子窗体精确定位在父窗体的某个位置,需要有目标坐标(这里将子窗体的位置设置为父窗体中一个panel的位置,需要将panel的坐标转换成屏幕坐标)

834
来自专栏Linux驱动

29.QT-自定义窗口拖动、自定义QToolButton/QPushButton开关按钮、界面阴影

2232

扫码关注云+社区