位图性能真的比矢量好吗?
随着chrome的更新,下面这些demo的部分数值对比已经不能作为参考,图片和canvas矢量的性能大幅度提升,图片超过了矢量svg,简单的canvas矢量超过cache的状态的矢量(具体还是视自己的电脑性能和chrome的版本)
位图性能比矢量好,是经常玩canvas人的常识。但是最近跟同事聊天的时候,他坚称svg性能比png高,这让我匪夷所思,为了证明我是对的,我跟往常一样写了demo,但是写着写着还真发现一点猫腻。
下面是同事的代码,为了不涉及公司机密,我把它摘出来了:
https://www.ajexoop.com/test/svg_test/index2.html
可以发现5000个对象才20帧,不出所料的性能糟糕(公司老项目因为特殊原因不能用canvas所以用了svg,svg也是矢量)
然后我信誓旦旦的写了位图版本的,原以为会性能大增,结果:
https://www.ajexoop.com/test/svg_test/index.html
结果性能非但没大增,反而有时候掉到个位数去了,这时候我仔细看了下代码。
svg版本:
<!DOCTYPE html> <html > <head> <meta charset="UTF-8"> <title>Title</title> <style> *{ padding: 0; margin: 0; } .svgPatterns{ position: absolute; left: 0; top: 0; font-size: 12px; width: 1920px; height: 1080px; } .container{ width: 1920px; height: 1080px; } .fps{ width: 200px; height: 40px; line-height: 40px; font-size: 30px; color: #ffffff; background-color: #000000; font-weight: bold; position: fixed; left: 0; top: 0; z-index: 100; } </style> </head> <body> <div id="app"> <svg class="svgPatterns" style="position: absolute; width: 0px; height: 0px;"> <symbol id="defect0"> <path d="M8,2.67A5.33,5.33,0,1,0,13.33,8,5.32,5.32,0,0,0,8,2.67ZM10.85,9H5.15V7.05h5.7ZM13.49,0h-11A2.51,2.51,0,0,0,0,2.51v11A2.51,2.51,0,0,0,2.51,16h11A2.51,2.51,0,0,0,16,13.49v-11A2.51,2.51,0,0,0,13.49,0ZM8,14.67A6.67,6.67,0,1,1,14.67,8,6.67,6.67,0,0,1,8,14.67Z"></path> </symbol> <symbol id="defect1"> <path d="M10.45,6.69a.83.83,0,0,1-.57.23.8.8,0,0,1-.56-.23.79.79,0,0,1,0-1.13L14.86,0H0V14.87L5.55,9.32a.8.8,0,1,1,1.14,1.13L1.14,16H16V1.14ZM6.8,3,3,6.77A.77.77,0,0,1,2.48,7a.81.81,0,0,1-.57-1.37L5.67,1.88a.8.8,0,0,1,1.13,0A.79.79,0,0,1,6.8,3Zm7,7.29-3.76,3.76a.78.78,0,0,1-.57.23.8.8,0,0,1-.57-1.36l3.77-3.76a.8.8,0,1,1,1.13,1.13Z"></path> </symbol> <symbol id="defect2"> <path d="M8,16a8,8,0,0,1-4.56-1.43A2,2,0,0,0,4.3,14a2.46,2.46,0,0,0,.6-2.23c-.05-.53-.05-.72.15-.92s.39-.2.92-.15a2.46,2.46,0,0,0,2.23-.6,2.5,2.5,0,0,0,.6-2.22c-.06-.54-.06-.73.14-.93s.39-.19.93-.14a2.47,2.47,0,0,0,2.22-.6A2.49,2.49,0,0,0,12.69,4c0-.53-.06-.72.14-.92s.39-.2.93-.14l.48,0A8,8,0,0,1,8,16ZM11.1,4.19c.06.54.06.73-.14.93s-.39.2-.93.14a2.47,2.47,0,0,0-2.22.6,2.46,2.46,0,0,0-.6,2.23c0,.53.06.72-.14.92s-.39.2-.93.14a2.48,2.48,0,0,0-2.22.61A2.48,2.48,0,0,0,3.31,12c.06.54.06.73-.14.93s-.39.19-.92.14l-.48,0A8,8,0,0,1,12.57,1.43,2.16,2.16,0,0,0,11.7,2,2.5,2.5,0,0,0,11.1,4.19Z"></path> </symbol> <symbol id="defect3"> <path d="M15.36,11.11a8,8,0,0,1-14.73,0,8,8,0,0,1,0-6.23,8,8,0,0,1,14.73,0,8,8,0,0,1,0,6.23ZM8,1.13A6.87,6.87,0,1,0,14.85,8,6.87,6.87,0,0,0,8,1.13ZM8,11.65A3.66,3.66,0,1,1,11.64,8,3.65,3.65,0,0,1,8,11.65Z"></path> </symbol> <symbol id="defect4"> <path d="M0,0V16H16V0ZM8,13.82A5.83,5.83,0,1,1,13.83,8,5.82,5.82,0,0,1,8,13.82Z"></path> </symbol> <symbol id="defect5"> <path d="M15.44,16H.56A.55.55,0,0,1,0,15.45V.55A.55.55,0,0,1,.56,0H15.44A.55.55,0,0,1,16,.55v14.9A.55.55,0,0,1,15.44,16ZM14.89,1.1H1.11V14.9H14.89ZM10.42,7.46a3,3,0,1,1-3,3A3,3,0,0,1,10.42,7.46Z"></path> </symbol> <symbol id="defect6"> <path d="M13.45,0H2.56A2.56,2.56,0,0,0,0,2.56H0V13.45A2.56,2.56,0,0,0,2.56,16H13.45A2.57,2.57,0,0,0,16,13.45V2.56A2.56,2.56,0,0,0,13.45,0Zm.77,10.91a.61.61,0,0,1-.18.24c-.19.14-.48.17-1.07,0A5.28,5.28,0,0,1,10.4,9.78c-.3-.31-.25-.32-.8-.95-.26-.3-.49-.55-.71-.77l-.38-.38a.58.58,0,0,1-.11.15,4.5,4.5,0,0,1,.08.51,4.83,4.83,0,0,1,1.28,1.78A3.77,3.77,0,0,1,10,11.23a2,2,0,0,0,.32.89,2.68,2.68,0,0,0,.66.64,3.55,3.55,0,0,1,.89.88,3.73,3.73,0,0,1,.53,1,.23.23,0,0,1-.13.32h0a.28.28,0,0,1-.34-.16,4.21,4.21,0,0,0-.49-.88,3.46,3.46,0,0,0-.83-.79,2.85,2.85,0,0,1-.78-.73,2.16,2.16,0,0,1-.39-1.12,3.78,3.78,0,0,0-.26-1,4.43,4.43,0,0,0-.7-1.11l.06,1.65c0,.3.13,1.44.12,2,0,0-.2,1.88-.79,1.87s-.62-2-.62-2c0-.58.09-1.41.09-1.78V9.17a5,5,0,0,0-.7,1.11,3.48,3.48,0,0,0-.24,1,2.37,2.37,0,0,1-.37,1.16,2.93,2.93,0,0,1-.79.78,3.57,3.57,0,0,0-.82.78,4.32,4.32,0,0,0-.5.89.26.26,0,0,1-.33.15.24.24,0,0,1-.18-.3h0a3.93,3.93,0,0,1,.57-1,3.42,3.42,0,0,1,.89-.89,2.51,2.51,0,0,0,.66-.64,1.8,1.8,0,0,0,.31-.89,4.5,4.5,0,0,1,.34-1.19A5,5,0,0,1,7.5,8.33l.08-.51a.4.4,0,0,1-.1-.15l-.37.38c-.21.23-.45.47-.71.77-.55.63-.49.64-.8.95a5.24,5.24,0,0,1-2.5,1.38c-.6.17-.89.14-1.07,0a.72.72,0,0,1-.19-.24m0,0a.78.78,0,0,1-.06-.37C1.78,9.93,2.39,9.41,3,9a16.61,16.61,0,0,1,3-1.54,4.6,4.6,0,0,1-.73-.11A4.65,4.65,0,0,1,4,6.76c-.38-.2-.76-.38-1.15-.54a8.53,8.53,0,0,0-1.64-.47.26.26,0,1,1,.09-.51A10.88,10.88,0,0,1,3,5.72a10.55,10.55,0,0,1,1.22.59,4.26,4.26,0,0,0,1.24.53,4.48,4.48,0,0,0,1.86,0V6.55c-1-.16-1.52-.45-1.66-.89a.9.9,0,0,1,.15-.74A1.08,1.08,0,0,0,6,4.36c0-.63-.55-1.18-1.36-1.95a9.52,9.52,0,0,0-1.18-1,.25.25,0,0,1-.06-.35A.27.27,0,0,1,3.8,1V1h0A10.87,10.87,0,0,1,5.06,2c.89.84,1.55,1.5,1.51,2.36a1.82,1.82,0,0,1-.27.78c-.08.21-.13.21-.08.35s.23.38,1.18.54a1.68,1.68,0,0,1,.08-.59H7.35A.42.42,0,0,1,7.11,5a.44.44,0,0,1,.44-.43h.08C7.73,4.21,7.87,4,8,4s.27.25.37.63h.07A.45.45,0,0,1,8.9,5h0a.44.44,0,0,1-.23.38H8.55A5.73,5.73,0,0,0,8.62,6c.94-.13,1.16-.4,1.16-.51a.54.54,0,0,0-.11-.35,1.68,1.68,0,0,1-.26-.78c-.05-.89.64-1.52,1.51-2.36a10.76,10.76,0,0,1,1.24-1,.27.27,0,0,1,.38.06.24.24,0,0,1-.07.35,9.06,9.06,0,0,0-1.17,1c-.8.77-1.39,1.32-1.35,1.95a1.25,1.25,0,0,0,.19.56.88.88,0,0,1,.15.74c-.14.46-.69.75-1.65.89v.29a4.48,4.48,0,0,0,1.86,0,4.26,4.26,0,0,0,1.24-.53A10.55,10.55,0,0,1,13,5.67a10.9,10.9,0,0,1,1.78-.49.29.29,0,0,1,.32.26.28.28,0,0,1-.17.3h-.05a9.55,9.55,0,0,0-1.66.48A9.4,9.4,0,0,0,12,6.78a5.35,5.35,0,0,1-1.36.56,4.48,4.48,0,0,1-.72.11A16.55,16.55,0,0,1,13,9c.64.42,1.27.94,1.25,1.55a1,1,0,0,1-.08.37"></path> </symbol> <symbol id="defect7"> <path d="M14,0H2A2,2,0,0,0,0,2V14a2,2,0,0,0,2,2H14a2,2,0,0,0,2-2V2A2,2,0,0,0,14,0ZM5.05,12.62c0,.47-.29.89-.63.89H3.7c-.35,0-.62-.39-.62-.89V3.38c0-.47.27-.89.62-.89h.74c.35,0,.64.39.64.89Zm3.94,0c0,.47-.29.89-.63.89H7.64c-.34,0-.63-.39-.63-.89V3.38c0-.47.29-.89.63-.89h.72c.34,0,.63.39.63.89Zm3.93,0c0,.47-.27.89-.62.89h-.74c-.35,0-.64-.39-.64-.89V3.38c0-.47.29-.89.64-.89h.72c.34,0,.62.39.62.89Z"></path> </symbol> <symbol id="defect8"> <path d="M15.37,4.89A7.94,7.94,0,0,0,11.11.63a8,8,0,0,0-6.22,0A8.12,8.12,0,0,0,2.35,2.34a8,8,0,0,0,0,11.32,8.12,8.12,0,0,0,2.54,1.71,8,8,0,0,0,6.22,0,7.94,7.94,0,0,0,4.26-4.26,8,8,0,0,0,0-6.22ZM6.5,12.24A3.35,3.35,0,0,1,3.15,8.9,6,6,0,0,1,4.67,5.74,20.73,20.73,0,0,1,6.11,4l.39-.4.38.4A20.73,20.73,0,0,1,8.32,5.74,6,6,0,0,1,9.84,8.9,3.35,3.35,0,0,1,6.5,12.24Zm5.92-5.67a1.64,1.64,0,0,1-1.16.48,1.61,1.61,0,0,1-1.15-.48,2.56,2.56,0,0,1-.55-1.49,8.43,8.43,0,0,1-.08-.93V3.62H10a8.52,8.52,0,0,1,.94.08,2.66,2.66,0,0,1,1.49.55A1.65,1.65,0,0,1,12.42,6.57Z"></path> </symbol> <symbol id="defect9"> <path d="M8,0a8,8,0,1,0,8,8A8,8,0,0,0,8,0ZM7.89,11a10.45,10.45,0,0,0,.52,2.59c-.2-.53-2.67-3-1.63-4.82.55-1,1.64-1.74,1.54-3.18a19.38,19.38,0,0,0-.6-2.82A4.61,4.61,0,0,1,9.78,5.27C10.44,7.89,7.78,9.08,7.89,11Zm3.66,0a9.9,9.9,0,0,0,.5,2.59c-.18-.53-2.66-3-1.61-4.82C11,7.72,12.06,7,12,5.56a17.08,17.08,0,0,0-.61-2.82,4.63,4.63,0,0,1,2.07,2.53c.65,2.62-2,3.81-1.87,5.7ZM4.08,11a9.91,9.91,0,0,0,.51,2.59C4.39,13,2,10.61,3,8.74,3.56,7.72,4.6,7,4.51,5.56a18.2,18.2,0,0,0-.62-2.82A4.59,4.59,0,0,1,6,5.27C6.61,7.89,4,9.08,4.08,11Z"></path> </symbol> </svg> <div class="container"> <svg style="width: 1920px;height: 1080px"> <g> <use v-for="item in list" :xlink:href="item.id" :x="item.x" :y="item.y" fill="#EA6B66" visibility="visible" ></use> </g> </svg> </div> <div class="fps">{{fps}}</div> </div> <script src="vue.min.js"></script> <script src="createjs-1.0.0.min.js.js"></script> <script> new Vue({ el: '#app', data: { list:[], fps:'FPS:0', }, created() { for(let i = 0; i < 5000;i++) { let _data = {x:parseInt(Math.random()*2000),y:parseInt(Math.random()*1000),id:'#defect' + parseInt(Math.random()*10), image:"icon" + parseInt(1 + Math.random()*9) + '.png',svg:"icon" + parseInt(1 + Math.random()*9) + '.svg'} this.list.push(_data) } const FPS = {}; const ticker = () =>{ FPS.date = new Date(); FPS.currentTime = FPS.date.getTime(); if(FPS.time!=0) { FPS.FPS = Math.ceil(1000/(FPS.currentTime - FPS.time)); } FPS.time = FPS.currentTime; this.fps = "FPS: "+FPS.FPS; } const tickerHandler = () =>{ for(let i = 0; i < this.list.length;i++) { let _data = this.list[i]; let _speed = Math.random() * 3; _data.x -=_speed; if(_data.x < -10) _data.x = 2000; this.$set(this.list,i,_data ); } ticker(); } createjs.Ticker.timingMode = createjs.Ticker.RAF; createjs.Ticker.addEventListener('tick',tickerHandler) //用原生的RAF也是一样的,我这里为了统一标准,用了createjs的 // const animate = ()=> { // for(let i = 0; i < this.list.length;i++) // { // let _data = this.list[i]; // let _speed = Math.random() * 3; // _data.x -=_speed; // if(_data.x < -10) _data.x = 2000; // this.$set(this.list,i,_data ); // } // ticker(); // requestAnimationFrame( animate ); // } // requestAnimationFrame(animate) }, methods: { } }) </script> </body> </html>
img版本:
<!DOCTYPE html> <html > <head> <meta charset="UTF-8"> <title>Title</title> <style> *{ padding: 0; margin: 0; } .fps{ width: 200px; height: 40px; line-height: 40px; font-size: 30px; color: #ffffff; background-color: #000000; font-weight: bold; position: fixed; left: 0; top: 0; z-index: 100; } </style> </head> <body> <div id="app"> <!-- <img :src="item.svg" v-for="item in list" :style="{'position': 'absolute','left':0,'top':0,'transform': `translate(${item.x}px,${item.y}px)`}">--> <img :src="item.image" v-for="item in list" :style="{'position': 'absolute','left':0,'top':0,'transform': `translate(${item.x}px,${item.y}px)`}"> <div class="fps">{{fps}}</div> </div> <script src="vue.min.js"></script> <script src="createjs-1.0.0.min.js.js"></script> <script> new Vue({ el: '#app', data: { list:[], fps:'FPS:0', }, created() { for(let i = 0; i < 5000;i++) { let _data = {x:parseInt(Math.random()*2000),y:parseInt(Math.random()*1000),id:'#defect' + parseInt(Math.random()*10), image:"icon" + parseInt(1 + Math.random()*9) + '.png',svg:"icon" + parseInt(1 + Math.random()*9) + '.svg'} this.list.push(_data) } const FPS = {}; const ticker = () =>{ FPS.date = new Date(); FPS.currentTime = FPS.date.getTime(); if(FPS.time!=0) { FPS.FPS = Math.ceil(1000/(FPS.currentTime - FPS.time)); } FPS.time = FPS.currentTime; this.fps = "FPS: "+FPS.FPS; } const tickerHandler = () =>{ for(let i = 0; i < this.list.length;i++) { let _data = this.list[i]; let _speed = Math.random() * 3; _data.x -=_speed; if(_data.x < -10) _data.x = 2000; this.$set(this.list,i,_data ); } ticker(); } createjs.Ticker.timingMode = createjs.Ticker.RAF; createjs.Ticker.addEventListener('tick',tickerHandler) //用原生的RAF也是一样的,我这里为了统一标准,用了createjs的 // const animate = ()=> { // for(let i = 0; i < this.list.length;i++) // { // let _data = this.list[i]; // let _speed = Math.random() * 3; // _data.x -=_speed; // if(_data.x < -10) _data.x = 2000; // this.$set(this.list,i,_data ); // } // ticker(); // requestAnimationFrame( animate ); // } // requestAnimationFrame(animate) }, methods: { } }) </script> </body> </html>
我发现他把所有的svg图片放到了一个svg里渲染,做到了类似canvas的效果,性能确实比位图高了。
我为了探寻事情的真相面子,把svg再拆出来做了个demo,也就是上面的注释解开,发现帧率差不多,但是cpu在位图的情况下消耗的小,所以同等条件下位图性能最好还是没问题的,但是在不用canvas的情况下并不明显(把所有的svg放到了一个svg里渲染,这是一个svg优化的好办法,大家也可以学习一下)。
之后,为了对比,我用canvas也做了个类似的demo:
https://www.ajexoop.com/test/svg_test/canvas.html
代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>canvas</title> <style> *{ margin: 0; padding: 0; } body{ overflow-x:hidden; } </style> </head> <body> <canvas id="canvas" width="1920" height="1080"></canvas> <script src="createjs-1.0.0.min.js.js"></script> <script src="FPS.js"></script> <script> const GRAPHICS_DATA_LIST = [ "AgeBKQgfgOgMgdQgMgfAMgeQANgfAfgMQAegMAeAMQAdAMAOAfQANAegNAfQgNAfgfAMQgPAGgPAAQgPAAgPgGgAgwgwQgUAUAAAcQAAAcAUAVQAUAUAcAAQAcAAAUgUQAUgUAAgdIAAAAQAAgbgTgVQgVgUgcAAQgcAAgUAUgAgZAaQgLgLAAgPQAAgOAKgLQALgLAPAAQAOAAALALQALAKAAAPQAAAPgLALQgKAKgPAAIAAAAQgPAAgKgKg", "Ag4A5QgXgYAAghQAAggAXgYQAXgXAhAAQAhAAAYAXQAXAYAAAgQAAAhgXAYQgYAXghAAQghAAgXgXgAApA4QgEgLgCgPQAAgHAMgTQALgQgEgOQgFgQgQgJQAEAMADAQQABAJgHAJIgKANQgGALAJASIAOATIAAAAgAAEA4QgEgKgBgQQAAgHALgTQALgQgEgOQgFgQgOgJIAFAcQABAJgGAJIgKANQgGALAKASIAMATIAAAAgAghA4QgFgOgBgMQAAgHAMgTQALgQgDgOQgGgRgPgIQAEAMACAQQABAJgGAJIgKAMQgGAMAJARQAFAJAIALIAAAAg", "AAABQQgZAAgUgOQAGgBADgFQAJgIgDgOQgBgHADgCQACgCAHABQANACAIgIQAJgKgDgMQgBgHACgCQACgCAIABQANACAJgIQAJgKgDgNQAAgHABgCQACgCAIABIAEAAQAVAagDAgQgDAhgaAUQgVASgbAAIgDAAgAg5AzIgEAAQgVgZADggQACghAZgWQAVgRAcgBQAagBAXAQQgFABgEAEQgJALADALQABAIgCACQgCACgIgBQgMgDgJAJQgJAKADALQAAAIgBACQgCACgIgBQgMgDgKAJQgJAKADAMQABAIgCACQgCABgFAAIgDAAg", "AgfBKQgNgGgMgLQgXgYAAghQAAggAXgYQAMgLANgGQAfgNAfANQAeANAMAeQAOAegOAfQgMAegeANQgQAGgPAAQgPAAgQgGgAgSgnIgPARQgMAPgDAQQAAAOAKAJQAKAKAOAAQANAAAJgKQAKgJAAgOQgCgQgNgPIgRgVgAAsgNQAFgFAAgHQAAgHgFgFQgHgEgIgBIgPgBIAAAGIABAJQAAAIAGAHQAFAFAGgBQAGABAGgFg", "AhPBQIAAifICfAAIAACfgAgogoQgRARAAAXQAAAZARAQQAQARAYABQAYgBARgRQARgQAAgZQAAgXgRgRQgRgRgYAAQgYAAgQARg", "AhEBQIA4g4QACgCAAgDQAAgDgCgCQgCgCgEAAQgDAAgCACIg4A3IAAiUICTAAIg3A4QgCACAAADQAAAEACACQADADACgBQADABADgDIA4g3IAACTgAAvAMIgmAmQgCACgBADQAAAIAIAAQAEAAACgCIAngmQAFgFgGgGQgDgDgDAAQgDAAgCADgAgWg8IgmAmQgDACAAADQABAIAHAAQAEAAACgCIAmgmQACgCAAgEQAAgDgCgCQgDgDgDAAQgDAAgCADg", "ABKBQIiUAAQgFABAAgGIAAiUQAAgGAFAAICUAAQAGAAgBAFIABABIAACTQAAAGgFAAgAhEBFICIAAIAAiJIiIAAgAADAuQgIgJAAgMQAAgNAIgIQAJgIAMAAQAMAAAJAIQAJAIAAANQAAAMgJAJQgJAJgMAAQgMAAgJgJg", "Ag7BQQgIAAgHgFQgFgHAAgIIAAh3QAAgIAFgGQAHgGAIAAIB3AAQAIAAAGAGQAGAGAAAIIAAB3QAAAIgGAHQgGAFgIAAgAAfgzQgCADAAADIAABcQAAAIAGABIAIAAQADgBABgDQACgCAAgDIAAhcQAAgJgHAAIgHAAQgCAAgCADgAgJgtIAABcQAAAIAGABIAHAAQACgBABgDQACgCAAgDIAAhcQAAgDgCgDQAAgBAAgBQgBAAAAAAQgBgBAAAAQgBAAAAAAIgHAAQgGAAAAAJgAgwgtIAABcQAAAIAGABIAHAAQADgBACgDQABgCAAgDIAAhcQAAgJgGAAIgHAAQgHAAABAJg", "AhIBJQgHgIAAgLIAAhrQAAgLAHgIQAIgHAKAAIBsAAQALAAAHAIQAIAHAAALIAABrQAAALgIAHQgHAIgLAAIhsAAIgBAAQgJAAgIgHgAgDgBIgBAEQgJAIgFAKIgCAIIgBAEQAAAFgDAEQgCAEgEACIgJAJQgEAFgCAFIAAABIAAABIABABQABABABAAQAAAAABAAQAAgBAAAAQABAAAAgBIAFgJQAEgFAEgDQAEgCAEgGQADgEABgHIAAgEIACgGIAHgLIAAAjIABAKQABAKADAAQAGAAABgTIgBgTIAAgRQAFAGACAFIACAGIAAAEQABAHADAEQACAEAGADQAFADADAFQAEAFABAEQAAABABABQAAAAAAAAQABAAAAAAQABAAAAAAIAAgBQABAAAAAAQABAAAAgBQAAAAAAgBQAAAAgBgBQgBgEgDgGQgFgFgEgDIgHgHQgDgDAAgGIgDgLQgEgKgIgIIgBgEIABgBIASAUQAJAIAKADIATAAIABgDQAAgHgMgJQgPgJgQgFIAHgCQAHgBAHgEIAMgGIAQgFIABAAQABAAAAAAQAAAAAAgBQABAAAAgBQAAAAgBgBQAAAAAAgBQAAAAAAAAQgBgBAAAAQgBAAAAAAQgIABgKAEIgNAGQgEADgJACQgJACgJgCIAAgDQAOgBADgHQABgEgDgEIgCgFQAAgHAOgNIALgKIAAAAQABAAAAgBQABAAAAAAQAAgBAAAAQAAgBgBAAQAAgBgBAAQAAAAgBAAQAAAAgBAAQAAAAgBAAIgMAKIgLAMQgEAGAAAGQAAAEACADIABAEQAAAEgLABIAAgGIAAAAQABAAAAAAQABgBAAAAQAAgBAAAAQAAgBAAgBQABgEgFAAIAAAAQgCgGgCAAQgBAAgCAGIAAAAQgFAAAAAEQAAABAAABQAAAAAAABQAAAAABABQAAAAABAAIACAAIgBAGQgLgBgBgEIAAgEQADgCABgFQAAgGgFgGIgLgMIgMgKQgBAAgBgBQAAAAgBAAQAAABAAAAQgBAAAAABIgBAAQAAAAAAABQAAAAAAABQAAAAABABQAAAAAAAAIAMAKQAOANAAAHIgCAFQgDAEACAEQACAGAOADIAAACQgJADgJgDQgIgBgFgEIgMgGIgRgFQgBAAgBABQAAAAgBAAQAAAAAAABQAAAAAAABQAAAAAAABQAAAAAAABQAAAAABAAQAAABABAAQAJABAHADIAMAGQAGAEAGABIAIACQgSAFgMAJQgNAIAAAHIABAEIAUAAQAKgDAIgIIAIgKIALgKg", "AhIBJQgHgHAAgLIAAhtQAAgKAHgIQAHgHAKAAIBtAAQALAAAHAHQAIAIAAAKIAABtQAAAKgIAIQgHAHgKAAIhtAAIgBAAQgKAAgHgHgAgvguQgTATAAAbQAAAcATATQAVAUAaAAQAcAAATgUQAUgUAAgbQAAgbgUgTQgTgUgcAAQgaAAgVAUgAglAmQgPgQgBgWQABgVAPgQQAQgPAVAAQAWAAAQAPQAPAQAAAVQAAAWgPAQQgQAPgWAAQgVAAgQgPgAgcAKIA5AAIAAgSIg5AAg", ] var canvas = document.getElementById('canvas'); var stage = new createjs.Stage(canvas); var shapeContainer = new createjs.Container(); stage.addChild(shapeContainer); FPS.startFPS(stage) for(var i = 0; i < 5000;i++) { var shape = new createjs.Shape(); var _data = GRAPHICS_DATA_LIST[parseInt(Math.random() * GRAPHICS_DATA_LIST.length)]; shape.graphics.f('#EA6B66').s().p(_data); shape.x = Math.random()*2000; shape.y = Math.random()*1000; // shape.cache(-8,-8,16,16) shapeContainer.addChild(shape); } createjs.Ticker.timingMode = createjs.Ticker.RAF; createjs.Ticker.addEventListener('tick',function (){ for(var i = 0; i < shapeContainer.numChildren;i++) { var shape = shapeContainer.getChildAt(i); var _speed = Math.random() * 3; shape.x -=_speed; if(shape.x < -10) shape.x = 2000; } stage.update(); }); </script> </body> </html>
发现帧数居然定死在了6……
这里可以得出一个结论:纯矢量,canvas的性能是不如svg的。
然后我把cache开启,再看性能。
非常丝滑,然后我用了位图也试了一下:
https://www.ajexoop.com/test/svg_test/canvas2.html
代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>canvas2</title> <style> *{ margin: 0; padding: 0; } body{ overflow-x:hidden; } </style> </head> <body> <canvas id="canvas" width="1920" height="1080"></canvas> <script src="createjs-1.0.0.min.js.js"></script> <script src="FPS.js"></script> <script> var imgList = [ {src:"icon1.png", id:"icon1"}, {src:"icon2.png", id:"icon2"}, {src:"icon3.png", id:"icon3"}, {src:"icon4.png", id:"icon4"}, {src:"icon5.png", id:"icon5"}, {src:"icon6.png", id:"icon6"}, {src:"icon7.png", id:"icon7"}, {src:"icon8.png", id:"icon8"}, {src:"icon9.png", id:"icon9"}, {src:"icon10.png", id:"icon10"}, ] var loader = new createjs.LoadQueue(false); loader.addEventListener("fileload", handleFileLoad); loader.addEventListener("complete", handleComplete); loader.loadManifest( imgList); var img = {} function handleFileLoad(event) { img[event.item.id] = event.result; } function handleComplete(event) { init() } function init() { var canvas = document.getElementById('canvas'); var stage = new createjs.Stage(canvas); var bitmapContainer = new createjs.Container(); stage.addChild(bitmapContainer); FPS.startFPS(stage) for(var i = 0; i < 5000;i++) { var bitmap = new createjs.Bitmap(img[imgList[parseInt(Math.random()*imgList.length)].id]); bitmap.x = Math.random()*2000; bitmap.y = Math.random()*1000; bitmapContainer.addChild(bitmap) } createjs.Ticker.timingMode = createjs.Ticker.RAF; createjs.Ticker.addEventListener('tick',function (){ for(var i = 0; i < bitmapContainer.numChildren;i++) { var bitmap = bitmapContainer.getChildAt(i); var _speed = Math.random() * 3; bitmap.x -=_speed; if(bitmap.x < -10) bitmap.x = 2000; } stage.update(); }); } </script> </body> </html>
依然非常丝滑,而且cpu消耗比cache还小,说明在canvas下,位图是大大优于矢量的,而且直接用位图也比cache性能稍好,不过差距不大。
这时候可能有小伙伴好奇了,开启webgl呢,毕竟canvas的优势是可以开启webgl啊,我这里也做了个demo
https://www.ajexoop.com/test/svg_test/webgl.html
100000个对象60帧,简直是降维打击,而且我这里还是一般的显卡,好的显卡我甚至看到过144帧的!
代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>canvas2</title> <style> *{ margin: 0; padding: 0; } body{ overflow-x:hidden; } </style> </head> <body> <canvas id="canvas" width="1920" height="1080"></canvas> <script src="createjs-1.0.0.min.js.js"></script> <script src="FPS.js"></script> <script> var imgList = [ {src:"icon1.png", id:"icon1"}, {src:"icon2.png", id:"icon2"}, {src:"icon3.png", id:"icon3"}, {src:"icon4.png", id:"icon4"}, {src:"icon5.png", id:"icon5"}, {src:"icon6.png", id:"icon6"}, {src:"icon7.png", id:"icon7"}, {src:"icon8.png", id:"icon8"}, {src:"icon9.png", id:"icon9"}, {src:"icon10.png", id:"icon10"}, ] var loader = new createjs.LoadQueue(false); loader.addEventListener("fileload", handleFileLoad); loader.addEventListener("complete", handleComplete); loader.loadManifest( imgList); var img = {} function handleFileLoad(event) { img[event.item.id] = event.result; } function handleComplete(event) { init() } function init() { var canvas = document.getElementById('canvas'); var stage = new createjs.StageGL(canvas); stage.setClearColor("#ffffff"); var bitmapContainer = new createjs.Container(); stage.addChild(bitmapContainer); FPS.startFPS(stage) for(var i = 0; i < 100000;i++) { var bitmap = new createjs.Bitmap(img[imgList[parseInt(Math.random()*imgList.length)].id]); bitmap.x = Math.random()*2000; bitmap.y = Math.random()*1000; bitmapContainer.addChild(bitmap) } createjs.Ticker.timingMode = createjs.Ticker.RAF; createjs.Ticker.addEventListener('tick',function (){ for(var i = 0; i < bitmapContainer.numChildren;i++) { var bitmap = bitmapContainer.getChildAt(i); var _speed = Math.random() * 3; bitmap.x -=_speed; if(bitmap.x < -10) bitmap.x = 2000; } stage.update(); // stage.updateViewport(canvas.width,canvas.height)//需要修改舞台大小时解开注释 }); } </script> </body> </html>
最后我来说一下结论:
同样的条件下,位图性能确实大于矢量,但是svg是经过优化的,在dom中和位图性能差别不大,并且如果是统一绘制性能还会比位图更好。
同样是矢量,svg比canvas性能好。
同样是位图,canvas比img标签好。
canvas可以手动切换矢量和位图,并且可以开启webgl,所以以后碰到需要大量渲染的项目,尽量首选canvas。
发表评论