导语: 几个星期前,由于公司活动,须要作一个比较炫酷的
H5
动画, 一顿猛如虎的coding
以后,发现运行起来卡成狗,当时绝望的想要出家,还好组内有经验比较丰富的动画大神帮忙调整,顺利度过难关。javascript
为何动画会有卡顿感?css
浏览器渲染绘制过程html
动画性能分析实战react
总结程序员
回答这个问题前,咱们应该要明白一个问题,为何咱们会感到动画在动?web
综上,咱们或以为动画卡,一个很大的缘由就是由于 FPS
(帧率) 太低致使,也就是说每一帧的画面不能的保证在16ms以内完成渲染工做,因此咱们会以为卡顿。chrome
解释清楚了会感到卡顿的缘由,你们是否是很好奇每一帧的渲染过程到底发生了什么会致使它的渲染时间超过 16ms ? canvas
如今进入到咱们的第二部分,浏览器渲染绘制过程浏览器
Webkit
的渲染流程为例分析下浏览器:处理HTML标记数据并生成DOM树。
处理CSS标记数据并生成CSSOM树。
将DOM树与CSSOM树合并在一块儿生成渲染树。
Layout(布局):计算每一个 DOM 元素在最终屏幕上显示的大小和位置。因为 web 页面的元素布局是相对的,因此其中任意一个元素的位置发生变化,都会联动的引发其余元素发生变化,这个过程叫 reflow
(回流 or 重排)。
Paint(绘制):在多个层上绘制 DOM 元素的的文字、颜色、图像、边框和阴影等。
composite(渲染层合并):按照合理的顺序合并图层而后显示到屏幕上。
每一帧的渲染通过如上步骤,呈如今用户的眼前,当这些步骤时间的总和 > 16ms, 用户就会有卡顿感产生。
在 动画性能分析 部分,会重点结合Layout
, Paint
, composite
部分来具体分析动画卡顿的缘由及优化方式,在此以前,咱们先了解下强大的 chrome
提供的性能分析工具,以便咱们更好分析问题。
使用 Performance 工具时,为了规避其它 Chrome 插件对页面的性能影响,咱们最好在无痕模式下打开页面
点击左上角实心圆开始录制,看下性能分析面板。
重点介绍下图中标红处:
FPS:这是一个和动画性能密切相关的指标,它表示每一秒的帧数。图中绿色柱状越高表示帧率越高,体验就越流畅。若出现红色块,则表明长时间帧,极可能会出现卡顿。图中以绿色为主,偶尔出现红块,说明网页性能并不糟糕,但仍有可优化的空间。
CPU:表示CPU的使用状况,不一样的颜色片断表明着消耗CPU资源的不一样事件类型。这部分的图像和下文详情面板中的Summary内容有对应关系,咱们能够结合这二者挖掘性能瓶颈。
summary: 渲染过程当中,每一个部分的耗时占比。
Paint flashing
, Layer borders
, FPS meter
:Paint flashing: 标记当前正在重绘的元素,(元素会被一个绿色的半透明遮罩蒙上),如上图;
Layer borders: 复合层
FPS meter: GPU性能监控
综上就是对
chrome
一些性能分析工具的简单介绍,说了这么多!!!让咱们写一些动画实操一下吧!!!![]()
下面就进入咱们最最重要的部分!!!动画性能分析实战
在浏览器中打开以下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style> .react {position: absolute;width: 100px;height: 100px;background: #f00;animation: react-run 3s linear 0s infinite;} @keyframes react-run { 0% { top: 0px;left: 0px;} 25% {top: 0px;left: 200px;} 50% {top: 200px;left: 200px;} 75% {top: 200px;left: 0px;} 100% {top: 0px;left: 0px;} } </style>
</head>
<body>
<div class="react"></div>
</body>
</html>
复制代码
运行结果:
性能分析:
图中移动的小方块在不停的重排重绘过程当中。
GPU 的内存使用率为2.4 ~ 4.9 之间。
一秒内重排和重绘的耗时分别为7.3ms
和4.9ms
。
这里还有个值得注意的点:
2.4
变为4.9
。以下图:
图层被光栅化后,分块存入GPU
的内存中,当元素跨光栅移动时,两块内存都在变化,因此消耗天然加倍啦!!!
好,如今让咱们开启传说中的 3D
引擎加速!!!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.react {position: absolute;
width: 100px;
height: 100px;
background: #f00;
animation: react-run 3s linear 0s infinite;
transform: translate3d(0, 0, 0);
}
@keyframes react-run {
0% {transform: translate3d(0, 0, 0);}
25% {transform: translate3d(200, 0, 0);}
50% {transform: translate3d(200, 200, 0);}
75% {transform: translate3d(0, 200, 0);}
100% {transform: translate3d(0, 0, 0);}
}
</style>
</head>
<body>
<div class="react"></div>
</body>
</html>
复制代码
运行结果:
性能分析:
图中移动的小方块没有发生重排和重绘,只有一个图层合并。
GPU 的内存使用率几乎为0。
一秒内重排和重绘的耗时分别为0ms
和0ms
,图层合并时间为89us
。
比较上述两种写法能够得处: 开启
GPU
加速时的动画性能要比不开启高效。
GPU
加速:GPU
加速:写到这里,你们可能会有疑问,为何开启GPU
加速就没有发生重排和重绘 ?是否是全部动画所有都开启GPU
加速,就会变的很快?
下面就来分析这两个问题:
GPU
加速就没有发生重排和重绘 ?观察上图:
在开启GPU
加速时,运动的红色方块开启了新的合成层,因此不用再重排
和重绘
,只须要一个合成图层的时间。
GPU
加速,就会变的很快?由于开启GPU
加速后会创建新的图层,新的图层就须要必定的内存空间,并且图层在合成时,图层越多耗费的时间确定也是越多的,因此疯狂的开启GPU
加速,不但不能解决性能问题,反而可能会带来性能问题。
以下 (GPU
内存使用较高):
综上所述: 合理的开启
GPU
加速,创建新的合成层,能够给性能带来很大的提高。
使用css
属性:
1. transform: translate3d(0, 0, 0);
2. will-change: '将会发生变化的属性';
复制代码
标签:
<video></video>
<canvas></canvas>
复制代码
chrome
开发工具对动画性能进行分析?GPU
加速和普通渲染的区别在哪里?GPU
加速?动画卡顿问题的分析,不像是查找
js
上的bug
,有逻辑可寻,因此在遇到问题时,咱们只有明白底层的原理,结合分析工具,才能更好的发现问题。