注册

使用transform和left改变位置的性能区别

使用transform和left改变位置的性能区别

现如今大多数设备的屏幕刷新频率是60Hz,也就是每秒钟屏幕刷新60次;因此网页动画的运行速度只要达到60FPS,我们就会觉得动画很流畅。

F(Frames) P(Per) S(Second) 指的画面每秒钟传输的帧数,60FPS指的是每秒钟60帧;换算下来每一帧差不多是16毫秒。 (1 秒 = 1000 毫秒) / 60 帧 = 16.66 毫秒/帧 复制代码但通常浏览器需要花费一些时间将每一帧的内容绘制到屏幕上(包括样式计算、布局、绘制、合成等工作),所以通常我们只有10毫秒来执行JS代码。

那么动画只要接近于60FPS就是比较流畅的,对比一下通过position:left 做动画和transform做动画的性能区别

假设每个人都是用性能最好的手机,浏览器,我们根本用不着去做性能优化,所以在这里为了效果明显,先将环境配置到较低,较差的情况下测试,动画也不能设置为单一的移动

1如何使用google开发者工具查看帧数

1.先按键盘F12, 然后点到performance

2.点击刷新按钮再按确定

image.png

3.把鼠标放在下面就是他对应的帧数

test5.gif

4.现在的浏览器(google为例)已经默认开启了硬件加速器,所以你去对比left和transform其实效果非常不明显,所以先把这个默认关掉

image.png

5.对比效果,应该是在低cpu的情况下测试,将他设置为6

test7.gif

6 查看GPU的使用

image.png

如果你是mac,勾选fps meter, 如果你是windows,勾选我上面写的

我是windows,但是我并看不到帧率的时时变化

7 如果你想查看层级

检查-> layers -> 选择那个可旋转的 -> 查看元素paint code的变化

如果你发现你没有layers, 可以看看三个点里面的more tools,把layers点出来

image.png

4transformcode.gif

2使用position:left (使用left并没有被提升到复合层)

<div class="ball-running"></div>
.ball-running {
width: 100px;
height: 100px;
animation: run-around 2s linear alternate 100;
background: red;
position: absolute;
border-radius: 50%;
}
@keyframes run-around {
0% {
top: 0;
left: 0;
}
25% {
top: 0;
left: 200px;
}
50% {
top: 200px;
left: 200px;
}
75% {
top: 200px;
left: 0;
}
}

3transformcode.gif


test2.gif


在cpu 4slown down的情况下,我们可以看到上面的FPS刚开始在60左右,后面掉到了4FPS,这个动画是不够流畅的.
帧率呈现出锯齿型


这是对应的帧率


image.png


在cpu6 slow down的帧率下甚至会出现掉帧的情况(下面那些红色的就是dropped frame)


test5.gif


3.使用transform进行做动画(transform提升到了复合层)

.ball-running {
width: 100px;
height: 100px;
animation: run-around 2s linear alternate 100;
background: red;
border-radius: 50%;
}
@keyframes run-around {
0% {
transform: translate(0, 0);
}
25% {
transform: translate(200px, 0);
}
50% {
transform: translate(200px, 200px);
}
75% {
transform: translate(0, 200px);
}
}

1transformcode.gif


4.从层级方向解释transform性能优于left


建议看这篇文章:
浏览器层合成与页面渲染优化


基本的渲染流程:


image.png


从左往右边看,我们可以看到,浏览器渲染过程如下:


1.解析HTML,生成DOM树,解析CSS,生成CSSOM树
(CSS Object Model ,CSS 对象模型,里面有很多api,包括style rules-内部样式表中所有的CSS规则)
2.将DOM树和CSSOM树结合,生成渲染树(Render Tree)
3.Layout(回流):根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小)
4.Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
5.display:将像素发送给GPU,展示在页面上。
复制代码

先了解下什么是渲染层


渲染层: 在 DOM 树中每个节点都会对应一个渲染对象(RenderObject),
当它们的渲染对象处于相同的坐标空间(z 轴空间)时,就会形成一个 RenderLayers,也就是渲染层。
复制代码

1先不涉及任何的层级问题

<div class="big">
</div>
<div class="small"></div>
<style>
.big {
width: 200px;
height: 200px;
background-color: yellow;
}
.small {
width: 100px;
height: 100px;
background-color: red;
}
</style>

1普通的代码.gif

从上面来看,只有一个渲染层

2加上index

<div class="big">
</div>
<div class="small"></div>
<style>
.big {
width: 200px;
height: 200px;
background-color: yellow;
position: relative;
}
.small {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
top: 0px;
left: 0px;
z-index: 10000;
}
</style>

1zindex.gif

从视觉上来看,small 的div确实是在big之上,但是和big在同一个渲染层上

3加上transform

<div class="big">
</div>
<div class="small"></div>
<style>
.big {
width: 200px;
height: 200px;
background-color: yellow;
position: relative;
}
.small {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
top: 0px;
left: 0px;
z-index: 10000;
transform: translateZ(0);
}

1transform.gif

如何形成合成层

42cd10c6f604ab0ba3b688a629f7744e.png

上面产生了一个新的层级,也就是合成层


首先,如果你改了一个影响元素布局信息的CSS样式,比如width、height、left、top等(transform除外),那么浏览器会将当前的Layout标记为dirty,因为元素的位置信息变了,将可能会导致整个网页其他元素的位置情况都发生改变,所以需要执行Layout全局重新计算每个元素的位置,如果提升为合成层能够开启gpu加速,并且在渲染的时候不会影响其他的层


并且在使用left的时候,document的paint code一直在变化,而使用transform的paint code一直都是不变的,可看上面的动画gif


有关于层级方面的东西,希望大家共同交流,我觉得自己也没有深刻的了解有些定义,只写了自己会的理解的,希望在查看操作方面能帮到大家



链接:https://juejin.cn/post/6959089368212439076

0 个评论

要回复文章请先登录注册