Web动画性能指南

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

索引
量化动画的流畅程度
了解浏览器的渲染机制
动画调优的策略与技巧
量化动画的流畅程度
动画的实现原理,是利用了人眼的“视觉暂留”现象,在短时间内连续播放数幅静止的画面,使肉眼因视觉残象产生错觉,而误以为画面在“动”。

动画相关的几个概念

帧:在动画过程中,每一幅静止画面即为一“帧”。
帧率:即每秒钟播放的静止画面的数量,单位是fps(Frame per second)。
帧时长:即每一幅静止画面的停留时间,单位一般是ms(毫秒)。
跳帧(掉帧/丢帧):在帧率固定的动画中,某一帧的时长远高于平均帧时长,导致其后续数帧被挤压而丢失的现象。
身边的帧率(频率):

10 FPS 达成基本视觉暂留
25~30 FPS 传统广播电视信号
60 FPS 浏览器渲染刷新频率
60~85 HZ 显示器刷新频率
100 HZ 日光灯管闪烁频率
帧率能反映动画的流畅程度

在网页中,帧率能够达到50~60fps的动画将会相当流畅,让人倍感舒适。
帧率在30~50fps之间的动画,因各人敏感程度不同,舒适度因人而异。
帧率在30fps以下的动画,让人感觉到明显的卡顿和不适感。
帧率波动很大的动画,亦会使人感觉到卡顿。
用帧率量化动画流畅度的几个例子

帧率稳定在60fps左右的流畅动画

帧率稳定但低于30fps的卡顿动画(帧率低导致卡顿)

平均帧率高,但存在跳帧现象的卡顿动画(帧率不稳定导致卡顿)

几款帧率监测工具

Stats.js,侦听全局或指定位置的帧率,JS实现,所有浏览器可用
Stats.js panel

Chrome自带的帧率监测工具,用于侦听全局帧率,以及页面重绘耗时
Chrome fps panel Chrome ms panel

Chrome Console

Chrome Timeline,杀手级监测 & 调试工具
Chrome Console

小结

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

帧率高(接近60fps最佳)
帧率稳定,波动少(极少出现跳帧现象)
ps: 或许有同学会有疑问:为什么电影/电视的帧率小于30fps,但依然感觉很流畅? 这个问题可以参阅这条知乎回答

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

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

浏览器的渲染引擎

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

来看两个例子:

Webkit的渲染流程 Webkit render flow

Gecko的渲染流程 Gecko render flow

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

几个关键的工作环节:

HTML解析(Parse HTML)
解析CSS(Parse CSS)
生成渲染树(Render Tree / Frame Tree)
排版/重排(Layout/Reflow)
绘图/重绘(Painting)
各款渲染引擎的基本工作流程可以抽象为下图: Render flow abstract

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

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

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

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

Chrome Timeline
Chrome Timeline

Safari Timeline
Safari Timeline

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

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

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

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

通过工具“看到”层

Chrome
Chrome Layer

Safari
Safari Layer

通过分层减小重绘面积

Chrome Layer root

如何创建新的层

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

触发普通元素的分层:
transform:translate3d属性(如transform:translateZ(0))
自带单独分层的元素
使用加速视频解码的元素
>元素
Flash等插件
动画调优的策略与技巧
提升每一帧性能(缩短帧时长,提高帧率)
避免频繁的重排。
避免大面积的重绘。
优化JS运行性能。
保证帧率平稳(避免跳帧)
不在连续的动画过程中做高耗时的操作(如大面积重绘、重排、复杂JS执行),避免发生跳帧。
若高耗时操作无法避免,则尝试化解,比如:
将高耗时操作放在动画开始或结尾处。
将高耗时操作分摊至动画的每一帧中处理。
针对硬件加速渲染通道的优化
通过层的变化效果(如transform)实现位移、缩放等动画,可避免重绘。
合理划分层,动静分离,可避免大面积重绘。
使用分层优化动画时,需要留意内存消耗情况(通过Safari调试工具)。
低性能设备优先调试
Android设备优先调试:移动设备的硬件配置一般低于桌面设备,而移动端设备中,Android设备相比于iOS设备性能普遍较差,因此在Andorid设备下性能问题更加明显,幸运的是Android可以借助Chrome自带的远程调试工具方便调试动画性能(Android 4.0+),所以优先调试Android设备可以更早地发现问题,并能更方便地解决问题。
本文仍在更新中,欢迎通过Github Watch关注更新动态

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

参考资料
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
Web动画性能指南 maintained by https://github.com/alexorz

Published with GitHub Pages

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值