兄dei,据说你动画很卡?

导语: 几个星期前,由于公司活动,须要作一个比较炫酷的H5动画, 一顿猛如虎的coding以后,发现运行起来卡成狗,当时绝望的想要出家,还好组内有经验比较丰富的动画大神帮忙调整,顺利度过难关。javascript

做为一个有追求的程序员!!!痛定思痛!!!一样的悲剧绝对不能在同一个技术面发生两次!!!流着泪写下该篇总结,但愿能够给你们一些启发。

本文目录:

为何动画会有卡顿感?

回答这个问题前,咱们应该要明白一个问题,为何咱们会感到动画在动web

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

  1. 大多数设备的刷新频率是 60 次/秒,(1000/60 = 16.6ms)也就说是浏览器对每一帧画面的渲染工做要在 16ms 内完成,超出这个时间,页面的渲染就会出现卡顿现象,影响用户体验。

综上,咱们或以为动画卡,一个很大的缘由就是由于 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 提供的性能分析工具,以便咱们更好分析问题。

强大的chrome性能分析工具介绍

  • performance

使用 Performance 工具时,为了规避其它 Chrome 插件对页面的性能影响,咱们最好在无痕模式下打开页面

点击左上角实心圆开始录制,看下性能分析面板。

重点介绍下图中标红处:

FPS:这是一个和动画性能密切相关的指标,它表示每一秒的帧数。图中绿色柱状越高表示帧率越高,体验就越流畅。若出现红色块,则表明长时间帧,极可能会出现卡顿。图中以绿色为主,偶尔出现红块,说明网页性能并不糟糕,但仍有可优化的空间。

CPU:表示CPU的使用状况,不一样的颜色片断表明着消耗CPU资源的不一样事件类型。这部分的图像和下文详情面板中的Summary内容有对应关系,咱们能够结合这二者挖掘性能瓶颈。

summary: 渲染过程当中,每一个部分的耗时占比。

  • Layers

是否是已经被这个高逼格的界面深深震撼到了!!!

重点看下 Paint flashing, Layer borders, FPS meter:

  • Paint flashing: 标记当前正在重绘的元素,(元素会被一个绿色的半透明遮罩蒙上),如上图;

  • Layer borders: 复合层

    1. 黄色边框: 有动画 3d 变换的元素,表示放到了一个新的复合层(composited layer)中渲染。
    2. 蓝色的栅格:这些分块能够看做是比层更低一级的单位,这些区域就是 RenderLayer。
  • FPS meter: GPU性能监控

    1. Frame Rate: 帧率。
    2. GPU Raster:GPU 光栅(默认开启)。
    3. GPU Memory: 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>
复制代码

运行结果:

  • Layers

  • performance

性能分析:

  1. 图中移动的小方块在不停的重排重绘过程当中。

  2. GPU 的内存使用率为2.4 ~ 4.9 之间。

  3. 一秒内重排和重绘的耗时分别为7.3ms4.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>
复制代码

运行结果:

  • Layers

  • performance

性能分析:

  1. 图中移动的小方块没有发生重排和重绘,只有一个图层合并。

  2. GPU 的内存使用率几乎为0。

  3. 一秒内重排和重绘的耗时分别为0ms0ms,图层合并时间为89us

比较上述两种写法能够得处: 开启GPU加速时的动画性能要比不开启高效。

  • 未开启GPU加速:
  • 开启GPU加速:

写到这里,你们可能会有疑问,为何开启GPU加速就没有发生重排和重绘 ?是否是全部动画所有都开启GPU加速,就会变的很快?

下面就来分析这两个问题:

1. 为何开启GPU加速就没有发生重排和重绘 ?

观察上图:

在开启GPU加速时,运动的红色方块开启了新的合成层,因此不用再重排重绘,只须要一个合成图层的时间。

2. 是否是全部动画所有都开启GPU加速,就会变的很快?

由于开启GPU加速后会创建新的图层,新的图层就须要必定的内存空间,并且图层在合成时,图层越多耗费的时间确定也是越多的,因此疯狂的开启GPU加速,不但不能解决性能问题,反而可能会带来性能问题

以下 (GPU内存使用较高):

综上所述: 合理的开启GPU加速,创建新的合成层,能够给性能带来很大的提高。

那么,都有那些放法创建新的合成层呢?

亲测有效的方法:

  • 使用css属性:

    1. transform: translate3d(0, 0, 0);
    2. will-change: '将会发生变化的属性';
    复制代码
  • 标签:

    <video></video>
    <canvas></canvas>
    复制代码

总结

经过此篇文章,咱们应该对动画性能分析有一个比较系统的认识:

  1. 为何会有卡顿感产生?
  2. 浏览器每一帧的渲染工做是怎么进行的?
  3. 如何使用chrome开发工具对动画性能进行分析?
  4. GPU加速和普通渲染的区别在哪里?
  5. 咱们应该如何开启GPU加速?

动画卡顿问题的分析,不像是查找js上的bug,有逻辑可寻,因此在遇到问题时,咱们只有明白底层的原理,结合分析工具,才能更好的发现问题。

相关文章
相关标签/搜索