关于cache必须要知道的后续操作(矢量同屏渲染大量对象教程)
注意:这里的矢量是指矢量图片,如果要同屏大量渲染动画,请博客里搜索spritesheetBuilder。
cache大家都知道,当对象子集太多或者太复杂的矢量或者有滤镜叠加模式的时候可以用来优化性能。但是cache在没有后续操作的情况下真的能优化性能吗?大家来看一下下面这个demo:
https://www.ajexoop.com/test/svg_test/canvas.html
大家打开这个demo和代码可以看到,这个demo加了cache反而会降低性能,把cache取消掉帧数居然回来了(大家可以down下来注释代码试试),所以可以得出结论:
在重复很多的情况下cache并不会增加性能,反而会降低性能!
这时候我用位图作为参造对比一下,位图应该有怎么样的性能:
https://www.ajexoop.com/test/svg_test/canvas2.html
可以看到60帧是满的,且没有用stageGL。
那怎么把矢量或者复杂对象彻底变成位图呢?我查了一下,其实还缺了一步,把他放到Bitmap中,那么怎么放呢?官网没有demo,GPT给了我答案:
// 创建一个矢量对象,例如一个圆形 var shape = new createjs.Shape(); shape.graphics.beginFill("#FF0000").drawCircle(0, 0, 50); // 缓存矢量对象 shape.cache(-55, -55, 110, 110); // 转换为位图对象 var bitmap = new createjs.Bitmap(shape.cacheCanvas); // 将位图对象添加到舞台 stage.addChild(bitmap);
是不是恍然大悟,原来cacheCanvas是这么用的(上面这个代码是我经我改良的,删除了gpt写的没用代码)
来试一下新代码:
https://www.ajexoop.com/test/svg_test/canvas3.html
不对,帧数还是没上去,问题出在哪呢?我考虑了下sprite的实现方式,还有flash年代,bitmap和bitmapData的关系,猜想是不是数据不共用导致的?
那我们接下去换下代码,把首次生成的bitmap放到数组里,后续拷贝他们的对象,以用来做数据共用,代码:
https://www.ajexoop.com/test/svg_test/canvas4.html
这个愉快的帧数回来了,跟位图一样快,那么我们得出结论:
当对象重复很多的情况下,不要使用new来生成对象,而是使用clone复制始祖对象。
然后我们再来讲讲替换方案:spritesheetbuilder,具体用法大家可以参考我过去的文章。其实spritesheetBuilder就是对刚刚那些步骤的封装,虽说是封装,但是由于spritesheetBuilder大头是用来封装movieclip的,所以只用起来做单帧转化也蛮麻烦的。不过优点是sprite本质是切换spritesheet的数据,所以new多个不用复制也是共享数据的,不会因为多个而卡顿,所以不需要clone。我们再说说二者的区别,一个是Sprite一个Bitmap,一个是异步转化,一个是同步转化,具体情况看使用场景,简单且转化少的情况下Bitmap包裹后clone对象更简单,复杂且转化对象多的话spritesheetBuilder更方便。当然如果是个movieclip那是铁定用spritesheetBuilder了。
接下来又到了炫技环节,如果用这个方法加上webgl同屏能渲染多少对象呢?看下面:
https://www.ajexoop.com/test/svg_test/canvas5.html
我这台电脑在140000个对象下同屏渲染59帧,可以说是非常爆炸了。
那么要渲染那么多对象干嘛呢?有项目需要这么做么?有!数据展示,粒子动画都用得到。
最后,撇末点题一下,如果要同屏渲染多个相同的单帧对象,需要先cache,后用Bitmap包裹变成始祖对象,后续生成的对象clone始祖对象,性能既可以跟位图一样丝滑。spritesheetBuilder可以作为替代方案,在单帧的情况,没有谁比谁优的情况,具体看业务逻辑和自己的习惯。
发表评论