上一篇讲动画原理的文章中,我说过要测试canvas动画的效率。说到做到!不过碰到一些让人尴尬的问题。
我由一个本来就有的html文件直接拖了两个副本出来,分别取名叫canvas版与html版,然后各自写了一个动画,但动画的外观是一样的,都是在一个800*600的区域中,一个红色正方形由左移动到右,周而复始——代码不重要,在文末。
由于chrome有任务管理器,可以查看各标签页的资源消耗情况,所以我是在chrome下测试的。
但还没开测就碰到个问题:canvas版的网页打开就有15000K的内存消耗,而html版的却只有7500K左右,我勒个去,这让我怎么测,这不是高下立判吗?
我把canvas版本的源码中JS删掉,甚至把canvas都删掉,结果打开时内存占用依然在10M以上,真是让人怒了。
不管,我决定开测,至少测出他们的内存波动。但在1个正方形的情况下,两者的内存占用都没什么波动。
于是我增加到30个,最后增加到180个。两者的内存依然无变化。而且,跟我印象中html元素越多网页就越吃内存的常识来比,貌似180个div并没让html版内存增加多少。
两个网页都如此淡定,实在让我不能淡定,于是我改了下代码——让每个正方形都随机定位,而不是简单的从左跑到右。而且,我把标签页拖出来,变成两个独立窗口
结果现在倒真的是高下立判!
-
初始内存占用html版依然是较低的一个。但开始运行后马上急剧升高,很快就超过canvas版的内存并超过20M。
-
当html版处于背面时,内存较稳定
-
当html版最小化后,内存占用急剧回落到初始水平,然后慢慢增加
-
用以上行动对待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。
测试代码打包下载
好了可以了,笔记本风扇已经疯狂了。