前端三种动画绘制效率对比
为了MG的开发,考虑了几种动画绘制的方案,开发量虽然不大,但是还是研究对比了一下几种方案的效率性能差异。
三种:Canvas序列帧动画,Lottie的JSON动画叠加绘制,Vue组件绑定gif动图叠加绘制。
对比主要考虑CPU,GPU,内存上的消耗,下面是测试代码:
<!DOCTYPE html> <html> <head> <title>Canvas tutorial</title> <style type="text/css"> canvas { border: 1px solid black; } * { margin: 0 } </style> </head> <body> <canvas id="tutorial"></canvas> <!-- 采用帧动画,资源消耗更少,胜在可控速度 内存稳定更少得多 绘制速率超过原gif大约1.2倍左右时。gpu占用率与img组件齐平 cpu相对也更低 --> </body> <script type="text/javascript"> var canvas; var ctx; var imgs=[]; function pre() { canvas=document.getElementById('tutorial'); ctx=canvas.getContext('2d'); canvas.width=window.innerWidth; canvas.height=500; for (let i=0; i<53; ++i) { imgs[i]=new Image(); // imgs[i].src="./imgs/动作-"+(i+1)+".png"; imgs[i].src="./new_imgs/动作-"+(i+1)+".png"; } var num=0; for (let i=0; i<imgs.length; ++i) { imgs[i].onload=function () { num++; console.log("num==", num); if (num==imgs.length) { start(); } } } }; pre(); function start() { var i=0; var time=2500; var fps=imgs.length; // 需要一个绘图中心 var x=imgs[0].width/2; var y=imgs[0].height/10*9; var len=80; ctx.fillStyle="rgb(100,100,0)"; setInterval(() => { ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.drawImage(imgs[i], 0, 0); ctx.drawImage(imgs[i], 0, 100); ctx.drawImage(imgs[i], 0, 200); i=(i+1==imgs.length? 0:i+1); // console.log("i==", i); }, time/fps); } </script> </html>
<!DOCTYPE html> <html> <head> <title>Canvas tutorial</title> <script type="text/javascript" src="./vue.min.js"></script> <script type="text/javascript" src="./vue.js"></script> <style type="text/css"> canvas { border: 1px solid black; position: relative; } img { position: absolute; /* top: 100px; left: 100px; */ } * { margin: 0 } </style> </head> <body> <!-- 采用img组件,cpu和内存和gpu占用率都更高 --> <canvas id="tutorial"></canvas> <div id="my_img"> <img v-show="flag" :src="src" alt="" :style="style1"> <img v-show="flag" :src="src" alt="" :style="style2"> <img v-show="flag" :src="src" alt="" :style="style3"> </div> <button type="button" onclick="change()">切换</button> </body> <script type="text/javascript"> const vm=new Vue({ el: "#my_img", data() { return { flag: false, src: "./new动作.gif", style1: { top: 100+'px', left: 100+'px' }, style2: { top: 200+'px', left: 100+'px' }, style3: { top: 300+'px', left: 100+'px' } } } }) function change() { Vue.set(vm, "flag", !vm.flag); console.log("执行切换", vm.flag); } var canvas; var ctx; var imgs=[]; function pre() { canvas=document.getElementById('tutorial'); ctx=canvas.getContext('2d'); canvas.width=window.innerWidth; canvas.height=500; ctx.save(); ctx.fillStyle="rgb(100,100,0)"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.restore(); }; pre(); </script> </html>
(Vue的jar包和图片资源就不给了,阅者有需要自行替换)
Canvas序列帧动画与Vue组件绑定GIF动图叠加动画对比结果是:
Canvas序列帧更优:
内存上,任何情况都远胜于Vue组件绑定方式
CPU和GPU,在近似的动图绘制速率情况下,Canvas仍然更优。
大约在1.2倍数左右,GPU消耗齐平
CPU的齐平倍率大概是1.5。
另外一点,对于叠加动画而言,不可能是单个动画怼进画面就完事了,还得要调绘制位置和动图大小,甚至是绘制速率同步。
在这一方面,Canvas序列帧动画绘制都能轻松做到,但是Vue组件绑定不能实现绘制速率的控制(硬要钻牛角尖,也可以去PS单独绘制一份自己制定的速率动图,但是总归是不如Canvas改一改参数就好更方便)
综上:Canvas的序列帧动画完胜,另外还有一个Lottie的Json动画绘制,参考:here
(结论也是序列帧更优,所以,这里就不去对比Vue组件绑定与Lottie的Json动画了)
【Over】

浙公网安备 33010602011771号