很多前端小伙伴都知道关于页面动画时候,transform 性能好。
但是为什么 transform 性能好,认知可能停留在这些信息上:
1、transform 不会引起回流与重绘
2、transform 会进行 GPU 加速
没了……
上面的答案是对的,但不够深入,我们现在进行更详细的说明,让你了解的更加透彻。
为什么 transform 不会引起回流和重绘
如果只是这么一句,其实意义不大,不知其所以然。
要知道上面的原因,得从浏览器的渲染原理说起来。
首先,要知道浏览器渲染 HTML 是怎么玩的。大体是下面几个流程:
1、解析 HTML 文件生成 DOM 与 CSSOM
2、结合 DOM 与 CSSOM 生成样式树
3、根据实际显示情况由样式树生成布局树
4、为布局树优化进行分层
5、开始提供绘制指令
6、优化绘制块进行分片绘制
7、对分片结果进行光栅化
8、开始绘图
上面步骤有很多细节本篇不做描述,我们再加一点额外信息进行说明:
一个标签页一个渲染进程(不考虑同域优化),一个渲染进程提供一个渲染主线程,一个渲染主线程负责 HTML、CSS、JavaScript 的处理。
为什么要加上面的这一节呢,因为我们要把再上面的 8 个流程分成两份,一份在渲染主线程、一份在非渲染主线程(合成线程),从第六步开始就不在渲染主线程上了,所以第五步叫提供绘制指令。
JS 是单线程,这个还记得不?
根据上面得知,JS 卡的是渲染主线程(因为目前就这个线程关于 JS),就卡它。
那么为什么 transform 性能好呢?因为 transform 不在主线程上。
transform 在上面的第八步开始出现,这是个很奇怪的知识点,transform 虽然写在样式里面,但是不会在主线程上面,它仅仅负责把对应的内容进行变化(变形、位移等)。
然后第八步还会有 GPU 加速,有 GPU 加速功能的电脑,都会调用这个能力。
综上两个点:
transform 不在主线程处理、还有 GPU 加速,所以 transform 性能好,而且特别好,快能赶上 Canvas 的那种好。能赶上 Canvas 是因为 Canvas 本就是纯绘制。
验证 transform 有多好
创建一个 index.html 文件,内部写上如下内容。
<style>
div {
position: relative;
left: 0;
width: 100px;
height: 100px;
border-radius: 50%;
}
@keyframes left {
0% {
left: 0;
}
100% {
left: 200px;
}
}
@keyframes tran {
0% {
transform: translateX(0);
}
100% {
transform: translateX(200px);
}
}
.red {
background-color: red;
animation: left linear 1s infinite alternate-reverse;
}
.blue {
background-color: blue;
animation: tran linear 1s infinite alternate-reverse;
}
</style>
<div class="red"></div>
<div class="blue"></div>
<script>
const init = Date.now()
while(1) {
if(Date.now() - init > 3000) {
break
}
}
console.log('结束')
</script>
可以两个地方测试 transform 线程情况。
一个是刷新页面,你会看到 left 的停了,而 tran 的还在动,可以理解与渲染线程无关;
二是3秒内动画,由于有个死循环,所以道理上动画应该卡住,但实际上你会发现 left 卡住了,但是 tran 还是正常跑,佐证与主线程无关。
补充
left 导致了样式变动,直接影响到样式树,从第二步就开始要计算,也就是所谓的回流;
tran 是最后一步而且不在主线程上,所以无关。