位图性能真的比矢量好吗?

  • 内容
  • 评论
  • 相关

随着chrome的更新,下面这些demo的部分数值对比已经不能作为参考,图片和canvas矢量的性能大幅度提升,图片超过了矢量svg,简单的canvas矢量超过cache的状态的矢量(具体还是视自己的电脑性能和chrome的版本)

位图性能比矢量好,是经常玩canvas人的常识。但是最近跟同事聊天的时候,他坚称svg性能比png高,这让我匪夷所思,为了证明我是对的,我跟往常一样写了demo,但是写着写着还真发现一点猫腻。

下面是同事的代码,为了不涉及公司机密,我把它摘出来了:

https://www.ajexoop.com/test/svg_test/index2.html

QQ图片20230310145039.png

可以发现5000个对象才20帧,不出所料的性能糟糕(公司老项目因为特殊原因不能用canvas所以用了svg,svg也是矢量)

然后我信誓旦旦的写了位图版本的,原以为会性能大增,结果:

https://www.ajexoop.com/test/svg_test/index.html

QQ图片20230310145124.png

结果性能非但没大增,反而有时候掉到个位数去了,这时候我仔细看了下代码。

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>

QQ图片20230310150329.png

发现帧数居然定死在了6……

这里可以得出一个结论:纯矢量,canvas的性能是不如svg的。

然后我把cache开启,再看性能。

QQ图片20230310162201.png

非常丝滑,然后我用了位图也试了一下:

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帧的!

image.png

代码:

<!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。

QQ图片20230310171328.png

评论

0条评论

发表评论

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