【转载】Web动画性能指南
特别声明:本文转载@Alexorz的《Web动画性能指南》,如需转载,烦请注明原文出处:http://alexorz.github.io/animation-performance-guide
引言
随着网页功能变得愈发复杂和精细,以及手机端H5发展中所遇到的硬件性能瓶颈,网页的运行时性能问题变得越来越突出。而用户对于网页运行时性能最直观的感受,莫过于UI操作的流畅程度。流畅或卡顿,爽或不爽,皆在于每个UI动画细节之间。本文旨在帮助理解动画卡顿与流畅的原因,卡顿问题的调试方法,以及从实践中总结出实现流畅动画的规律。为构建操作流畅的网页提供参考。
量化动画的流畅程度
动画的实现原理,是利用了人眼的“视觉暂留”现象,在短时间内连续播放数幅静止的画面,使肉眼因视觉残象产生错觉,而误以为画面在“动”。
动画相关的几个概念
- 帧:在动画过程中,每一幅静止画面即为一“帧”。
- 帧率:即每秒钟播放的静止画面的数量,单位是
fps
(Frame per second)。 - 帧时长:即每一幅静止画面的停留时间,单位一般是
ms
(毫秒)。 - 跳帧(掉帧/丢帧):在帧率固定的动画中,某一帧的时长远高于平均帧时长,导致其后续数帧被挤压而丢失的现象。
身边的帧率(频率):
- 10FPS达成基本视觉暂留
- 25~30FPS 传统广播电视信号
- 60FPS浏览器渲染刷新频率
- 60~85HZ显示器刷新频率
- 100HZ日光灯管闪烁频率
帧率能反映动画的流畅程度
- 在网页中,帧率能够达到
50~60fps
的动画将会相当流畅,让人倍感舒适。 - 帧率在
30~50fps
之间的动画,因各人敏感程度不同,舒适度因人而异。 - 帧率在
30fps
以下的动画,让人感觉到明显的卡顿和不适感。 - 帧率波动很大的动画,亦会使人感觉到卡顿。
用帧率量化动画流畅度的几个例子
帧率稳定在60fps左右的流畅动画
帧率稳定但低于30fps的卡顿动画(帧率低导致卡顿)
平均帧率高,但存在跳帧现象的卡顿动画(帧率不稳定导致卡顿)
几款帧率监测工具
Stats.js,侦听全局或指定位置的帧率,JS实现,所有浏览器可用
Chrome自带的帧率监测工具,用于侦听全局帧率,以及页面重绘耗时
Chrome Timeline,杀手级监测 & 调试工具
小结
帧率能够量化动画的流畅程度,流畅的动画一般具备两个特点:
- 帧率高(接近60fps最佳)
- 帧率稳定,波动少(极少出现跳帧现象)
了解浏览器的渲染机制
每当性能提升工作遇到瓶颈时,我们总是会尝试从底层实现机制中寻找突破口。动画性能优化也不例外,想要将动画性能提升到极致,首先我们需要知道浏览器是如何渲染每一帧的。
浏览器的渲染引擎
各厂出品的浏览器所用的渲染引擎不尽相同: IE使用Trident ,FireFox使用Gecko ,Safari使用WebKit ,Chrome 28+ 和 Opera 15+使用的是Blink(WebKit的分支)。
来看两个例子:
Webkit的渲染流程
Gecko的渲染流程
虽然浏览器款式如此之多,但当我们对比WebKit和Gecko这两款引擎的工作流程,会发现二者大体的流程以及一些关键环节还是基本相同的。
几个关键的工作环节:
- HTML解析(Parse HTML)
- 解析CSS(Parse CSS)
- 生成渲染树(Render Tree / Frame Tree)
- 排版/重排(Layout/Reflow)
- 绘图/重绘(Painting)
各款渲染引擎的基本工作流程可以抽象为下图:
可见,对于通过修改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
Safari
通过分层减小重绘面积
如何创建新的层
从目前来看(Chrome、Safari等现代浏览器仍在不断迭代演进),以下情况下元素会创建自己的层(包括但不限于以下情况,待完善):
触发普通元素的分层:transform:translate3d
属性(如transform:translateZ(0)
)
自带单独分层的元素
- 使用加速视频解码的
<video>
元素 <iframe>
元素- Flash等插件
动画调优的策略与技巧
提升每一帧性能(缩短帧时长,提高帧率)
- 避免频繁的重排。
- 避免大面积的重绘。
- 优化JS运行性能。
保证帧率平稳(避免跳帧)
- 不在连续的动画过程中做高耗时的操作(如大面积重绘、重排、复杂JS执行),避免发生跳帧。
- 若高耗时操作无法避免,则尝试化解,比如:将高耗时操作放在动画开始或结尾处。将高耗时操作分摊至动画的每一帧中处理。
针对硬件加速渲染通道的优化
- 通过层的变化效果(如
transform
)实现位移、缩放等动画,可避免重绘。 - 合理划分层,动静分离,可避免大面积重绘。
- 使用分层优化动画时,需要留意内存消耗情况(通过Safari调试工具)。
低性能设备优先调试
Android设备优先调试:移动设备的硬件配置一般低于桌面设备,而移动端设备中,Android设备相比于iOS设备性能普遍较差,因此在Andorid设备下性能问题更加明显,幸运的是Android可以借助Chrome自带的远程调试工具方便调试动画性能(Android 4.0+),所以优先调试Android设备可以更早地发现问题,并能更方便地解决问题。
扩展阅读
- High Performance Animations
- How Browsers Work: Behind the scenes of modern web browsers
- Accelerated Rendering in Chrome
- Performance profiling with the Timeline
- Profiling Long Paint Times with DevTools’ Continuous Painting Mode
- Scrolling Performance
- GPU Accelerated Compositing in Chrome
- Jank Busting for Better Rendering Performance
- Rendering: repaint, reflow/relayout, restyle
- How (not) to trigger a layout in WebKit
特别声明:本文转载@Alexorz的《Web动画性能指南》,如需转载,烦请注明原文出处:http://alexorz.github.io/animation-performance-guidejordans for sale infrared