Html5 canvas画图教程19:canvas动画与HTML动画效率对比

本文还是属于《html5 Canvas画图系列教程

上一篇讲动画原理的文章中,我说过要测试canvas动画的效率。说到做到!不过碰到一些让人尴尬的问题。

我由一个本来就有的html文件直接拖了两个副本出来,分别取名叫canvas版与html版,然后各自写了一个动画,但动画的外观是一样的,都是在一个800*600的区域中,一个红色正方形由左移动到右,周而复始——代码不重要,在文末。

由于chrome有任务管理器,可以查看各标签页的资源消耗情况,所以我是在chrome下测试的。

但还没开测就碰到个问题:canvas版的网页打开就有15000K的内存消耗,而html版的却只有7500K左右,我勒个去,这让我怎么测,这不是高下立判吗?

我把canvas版本的源码中JS删掉,甚至把canvas都删掉,结果打开时内存占用依然在10M以上,真是让人怒了。

不管,我决定开测,至少测出他们的内存波动。但在1个正方形的情况下,两者的内存占用都没什么波动。

于是我增加到30个,最后增加到180个。两者的内存依然无变化。而且,跟我印象中html元素越多网页就越吃内存的常识来比,貌似180个div并没让html版内存增加多少。

两个网页都如此淡定,实在让我不能淡定,于是我改了下代码——让每个正方形都随机定位,而不是简单的从左跑到右。而且,我把标签页拖出来,变成两个独立窗口

结果现在倒真的是高下立判!

  1. 初始内存占用html版依然是较低的一个。但开始运行后马上急剧升高,很快就超过canvas版的内存并超过20M。
  2. 当html版处于背面时,内存较稳定
  3. 当html版最小化后,内存占用急剧回落到初始水平,然后慢慢增加
  4. 用以上行动对待canvas版,其内存一直很稳定,不管是最小化,最前方,还是在背面。

由此看来,canvas的动画效率很是不错,可能初始内存要高些,但在中等复杂的情况下,内存连增加都不得增加。

而html版的动画,表现为初始消耗少,动起来就要命,波动大。由此看来javascript的瓶颈真的是卡在DOM操作上。

发现canvas的优点后,我故意把正方形的个数增加到1800个(很好改,一个变量),结果canvas内存依然没什么变化——可能是因为超过canvas范围的方形画出来也消耗不了资源

于是我又改变代码,让正方形不可能超出canvas的范围,结果出现了一片大红——但是,网页的内存还是没什么变化!

所以说,如果你要写游戏的话,无疑canvas是你的最佳选择,除非在非常极端的情况(这种情况估计html版早已吐血过世)下,不用担心其效率。

测试核心代码,也可在最后下载打包的源码:

html版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<style type="text/css">
    #wrap {box-shadow: 0 0 10px rgba(0,0,0,0.2);width:800px;height:600px; position: relative; overflow: hidden; }
    .box {width: 50px; height: 50px; background-color: #f00; position: absolute; top: 100px;}
    </style>
<div id="wrap">
    <div class="box"></div> <!-- 复制180个 -->
</div>
...
<script type="text/javascript">
var box = document.getElementById('box'),
    wrap = document.getElementById('wrap'),
    boxes =wrap.getElementsByTagName('DIV'),
    width = wrap.offsetWidth,
    num = boxes.length,
    qi = 0;
for (var i=0;i<num;i++) {
    boxes[i].style.top = 20*i+'px'; //先设好top,这样一来大部分DIV都跑到了#wrap外,且设置了超出隐藏
}
~function animate () {
    // console.log(t);
    for (var i=0;i<num;i++) {
        boxes[i].style.left = qi*Math.random()+'px'; // 只设置left没有管top噢
        // boxes[i].style.left = qi+'px';
    }
    if(qi++ > width) {
        qi = 0;
    }
    window.setTimeout(animate,20)
}()
</script>

canvas版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<canvas id="cvs" width="800" height="600">不支持canvas</canvas>
<script type="text/javascript">
var cvs = document.getElementById('cvs'),
    width = cvs.width, //800
    height = cvs.height,
    ctx = cvs.getContext('2d'),
    qi = 0, t = 600, num = 1800; //注意,是1800
ctx.fillStyle="#f00";  
// ctx.fillRect(0,0,100,100);
~function animate () {
    // console.log(t);
    ctx.clearRect(0,0,width,height);
    for(var i=0;i<num;i++) {
        // ctx.fillRect(qi*Math.random(),t*i,50,50);
        ctx.fillRect(qi*Math.random(),t*Math.random(),50,50); //而且全部随机定位哟
    }  
    if(qi++ > width) {
        qi = 0;
    }
    window.setTimeout(animate,20)
}()
</script>

以上代码中,html版已经占了不少便宜,比如我并没有让所有DIV都在可见区域显示出来,但在效率上却力不从心。这应该是由于元素太多造成的,而canvas不管怎么弄,始终只有一个元素。

PS,由源码可以发现,canvas版可要少很多代码量噢——当然,html版也可由JS生成DIV。

测试代码打包下载

好了可以了,笔记本风扇已经疯狂了。

《Html5 canvas画图教程19:canvas动画与HTML动画效率对比》有1个想法

发表评论

电子邮件地址不会被公开。