高性能动画

参考资料http://melonh.com/sharing/slides.html?file=high_performance_animation#/
奇舞团黄薇

一、简介

        先按照浏览器渲染页面的顺序介绍下浏览器是如何渲染一个页面的。结合chrome开发工具中的timeline。
1、解析HTML--对应chrome中的Parse HTML
2、根据解析后的Dom节点和CSS构成了render-tree -- 对应timeline中的Recalculate Style
3、再由render-tree进行第一次渲染,将css中的布局属性(宽高大小定位)结合dom渲染 -- Layout
4、第二次渲染,将css中的跟展示效果相关的属性结合dom进行渲染 -- Paint
5、将Paint给到GPU,再显示在浏览器上,或者经过transform偏移旋转缩放透明度等绘制,最后渲染到屏幕上 -- Composite Layer

        小结:三个渲染过程都是对各自对应的css属性。即当某属性改变时,会对应到各自的渲染步骤开始重新绘制。当涉及到transform偏移旋转缩放时会生成新的脱离的layer,在GPU中独立绘制

二、硬件加速

        如何开启硬件加速就不说了,接下来讲讲其原理,就拿开个定时器对css属性margin-left translateY两者改变大小做个说明。
        由第一部分可知修改了margin-left属性时会触发Layout的重绘,然后是Paint、composite,即将Paint给到GPU进行处理,假设每一秒修改margin-left一次,那么每一秒都会进行Layout 和paint的重绘,而这两者又是很需要时间的。
        而定时修改translateY,因为这个步骤已经在第三个步骤,并不影响layout和paint,所以直接在GPU中重绘,省去了多次的layout、paint的重绘时间。这里就节省了大量的时间。
        至于为何节省了时间就能大大提升动画的性能和流畅度,第三节分析。

三、60FPS 屏幕刷新时间

        大部分的屏幕每一秒会有60帧的画面,如果我们做好了每一帧的画面就能产生流畅的动画效果,而每一帧需要的时间是16.7ms。这也就意味着我们要赶在16.7秒之前要根据css重绘好页面,以备给浏览器每隔16.7秒的刷新所需的页面,如果没准备好,动画也就会有一些停顿,产生卡顿的感觉。
        所以我们需要对三个渲染阶段都要尽可能的压缩时间。
        接下来谈谈间隔时间问题,就是动画时采用的间隔时间,以前采用的是setTimeout(callback, 1000/60),但这个方法会有掉帧的现象,而html5得新特性requireAnimationFrame方法,是根据浏览器的每一帧需要的时间自动设置,这样就无需担心掉帧的问题,值得注意的是这个方法的兼容性。

四、三个渲染阶段的优化

layout
        layout主要跟css中的布局属性改变有关,而这个也是大多数动画的基础。对于layout属性的读或写都会有可能导致layout的重绘。
        区别在于如果单纯是js中写属性,浏览器会把一段时间的写操作集中在一个时间段进行layout的重绘,并不是想象中的每当重写一个css-top属性就会重绘一次。
        而写完属性又去读其他elem的top等属性,浏览器会强制进行layout的重绘,理由是这个读取操作可能会受上次的写操作的影响,导致读取错误。
        根据上面的理论我们以后再js中写操作css的语句时,尽可能的写操作写一起,读操作写一起。

// Read
var h1 = element1.clientHeight;
var h2 = element2.clientHeight;
var h3 = element3.clientHeight;

// Write
element1.style.height = (h1 * 2) + 'px';
element2.style.height = (h2 * 2) + 'px';
element3.style.height = (h3 * 2) + 'px';

paint
        paint渲染阶段是当css改变了border-radius,color,box0shadow等展示型属性是触发的。
        关于此阶段可以优化的点罗列在下面:

  • gif图片也会时时出发paint,而且当zindex而看不见时还是会触发,所以不用时最好display=none

composite layer
        避免生成独立的layer层,因为在手机端GPU是有限制的,没有pc那么强大。
        z-index比layer层要高的元素也会自动生成layer。

标签: none

添加新评论