前言

最近再弄快成长移动端官网,产品提出了个需求,要求实现页面向下滚动导航栏顶部吸附的效果,其中发现几处好玩的地方。

知识点补充

60fps和设备刷新率

当今大多数设备的屏幕刷新率都是 60次/秒 。因此,如果在页面中有一个动画或渐变效果,或者用户正在滑动页面,那么浏览器渲染动画或页面的每一帧的速率,也需要跟设备屏幕的刷新率保持一致。

也就是说,浏览器对每一帧画面的渲染工作需要在16毫秒(1秒 / 60 = 16.66毫秒)之内完成。但实际上,在渲染某一帧画面的同时,浏览器还有一些额外的工作要做(比如渲染队列的管理,渲染线程与其他线程之间的切换等等)。因此单纯的渲染工作,一般需要控制在10毫秒之内完成,才能达到流畅的视觉效果。如果超过了这个时间限度,页面的渲染就会出现卡顿效果,也就是常说的jank,它是很糟糕的用户体验。

CSS3硬件加速

现代浏览器大都可以利用GPU来加速页面渲染。在GPU的众多特性之中,它可以存储一定数量的纹理(一个矩形的像素点集合)并且高效地操作这些纹理(比如进行特定的移动、缩放和旋转操作)。这些特性在实现一个流畅的动画时特别有用。浏览器不会在动画的每一帧都绘制一次,而是生成DOM元素的快照,并作为GPU纹理(也被叫做层)存储起来。之后浏览器只需要告诉GPU去转换指定的纹理来实现DOM元素的动画效果。这就叫做GPU合成,也经常被称作『硬件加速』。

最佳实践一

下面是个两个测试demo
demo1卡顿版demo2加速版

首先在chrome Dev tool中console 选出Rendering,选择FPS Meter 和 Paint Flashing(如图)。
因为现在设备的配置已经相当高了,所以demo采用的比较暴力的方法。如图示中外圈并非采用border,而是采用border-shadow,我们知道box-shadow的动画变化会比较损耗性能。再者将其中的

重复n遍,放大box-shadow动画变化的性能损耗。

FPS Meter:Plots frames per second,frame rate distribution,and GPU memory(帧的持续绘制模式状态表,记录绘制速率和GPU的内存使用情况)
Paint Flashing:Highlights areas of the page that need to be repainted(监控repaint区域,发生重绘则会高亮显示)

测试一结果


测试二结果



实验结果表明,实验一页面渲染绘制在每秒60帧或以上(为什么停留在60fps呢?哈哈,因为电脑设备设置每秒刷新页面60次啊,就是60HZ),且动画发生过程没有发生重绘;实验二页面渲染绘制在每秒30帧左右,出现了明显的卡顿,且发生了重绘。

综上所述,当我们用transform: translate属性代替top、left去实现元素的动画效果,已经开启了CSS3硬件加速并且过程不会发生重绘,动画由GPU控制,创建了一个独立 的复合图层(在Rendering中选择Layer Borders,则可以显示出独立符合图层,如图)

最佳实践二

从 top: 0 到 tranform: translate3d(0px,zpx,0px)

参考:

How to Use the Timeline Tool
An Introduction to Hardware Acceleration with CSS Animations
CSS动画之硬件加速