Web动画性能指南 Beta

Animation performance guide book for the (mobile) web

引言

随着网页功能变得愈发复杂和精细,以及手机端H5发展中所遇到的硬件性能瓶颈,网页的运行时性能问题变得越来越突出。而用户对于网页运行时性能最直观的感受,莫过于UI操作的流畅程度。流畅或卡顿,爽或不爽,皆在于每个UI动画细节之间。本文旨在帮助理解动画卡顿与流畅的原因,卡顿问题的调试方法,以及从实践中总结出实现流畅动画的规律。为构建操作流畅的网页提供参考。

索引

量化动画的流畅程度

动画的实现原理,是利用了人眼的“视觉暂留”现象,在短时间内连续播放数幅静止的画面,使肉眼因视觉残象产生错觉,而误以为画面在“动”。

动画相关的几个概念
身边的帧率(频率):
帧率能反映动画的流畅程度
用帧率量化动画流畅度的几个例子
几款帧率监测工具

Stats.js panel

Chrome fps panel Chrome ms panel

Chrome Console

Chrome Console

小结

帧率能够量化动画的流畅程度,流畅的动画一般具备两个特点:

ps: 或许有同学会有疑问:为什么电影/电视的帧率小于30fps,但依然感觉很流畅? 这个问题可以参阅这条知乎回答

因此,准确来说,前面所说的最佳帧率60fps,以及帧率小于30fps的动画出现卡顿感觉,前提是动画中没有加入模糊等特效。

了解浏览器的渲染机制

每当性能提升工作遇到瓶颈时,我们总是会尝试从底层实现机制中寻找突破口。动画性能优化也不例外,想要将动画性能提升到极致,首先我们需要知道浏览器是如何渲染每一帧的。

浏览器的渲染引擎

各厂出品的浏览器所用的渲染引擎不尽相同: IE使用Trident ,FireFox使用Gecko ,Safari使用WebKit ,Chrome 28+ 和 Opera 15+使用的是Blink(WebKit的分支)。

来看两个例子:

虽然浏览器款式如此之多,但当我们对比WebKit和Gecko这两款引擎的工作流程,会发现二者大体的流程以及一些关键环节还是基本相同的。

几个关键的工作环节:

各款渲染引擎的基本工作流程可以抽象为下图: Render flow abstract

可见,对于通过修改HTML元素CSS样式实现的动画,每修改一次CSS,浏览器就会做一次上图中CSS解析及其随后的操作。 (但并不是每一次对CSS的修改都会重新排版和绘图)

通过工具监测浏览器渲染行为

目前对浏览器渲染行为的监测,实现较好的是Chrome与Safari,并且这两者能远程调试Android和iOS设备中的Chrome和Safari浏览器(Chrome在Android 4.0后开始支持)。

借助Chrome和Safari的Timeline工具,分析耗时较长的帧,我们便能定位到渲染耗时长的原因,并针对问题原因寻找解决方案。

Chrome Timeline

Safari Timeline

现代浏览器的硬件加速渲染通道以及层模型(Layer model)

近些年来,现代浏览器借助于显卡的优势改变了渲染操作:通常被笼统的称为“硬件加速(hardware acceleration)”。

以Chrome为例,在硬件加速渲染通道下,复杂的页面会被分为多个层(Layer), Chrome对各个层分别进行排版、绘图,再将绘图结果作为“纹理”上传至GPU, 由GPU完成层的3D变换(transform)等操作,最后再将GPU渲染好的层图像进行复合操作(Compesite Layers),得到最终的画面结果。 因此,通过3D变换实现的位移、旋转、缩放将不会触发浏览器重绘(除非层的内容发生改变)。

可见,可以避免重绘的层模型对于动画调优有着重大意义。

通过工具“看到”层

Chrome Layer

Safari Layer

通过分层减小重绘面积

Chrome Layer root

如何创建新的层

从目前来看(Chrome、Safari等现代浏览器仍在不断迭代演进),以下情况下元素会创建自己的层(包括但不限于以下情况,待完善):

动画调优的策略与技巧

本文仍在更新中,欢迎通过Github Watch关注更新动态

有更多想法,欢迎交流,想要拍砖、指正、提建议,请戳这里

参考资料