最近在学校机房上前端课,用到了之前偶然看到的 CSS 的 GPU 渲染,性能肉眼可见提升。
前言
上课摸鱼整了个背景变色动画玩,发现卡到起飞,感觉帧数不到 10。开下任务管理器发现 CPU 满了,GPU 大概跑了一半。 试着用了所谓的“GPU 加速”后,情况改善不少,虽然还是远没有到达 30 帧。
在这机房上课真的折磨。
原理
CSS 的动画,变换和过渡并不会自动启用 GPU 加速,而是使用浏览器更慢的软件渲染引擎执行。 而许多浏览器提供了使用某些CSS规则的时候开启 GPU 加速渲染的功能。
主流的,像 Chrome、FireFox、Edge 和 Safari 这样的浏览器都支持硬件加速。
在 CSS 中,加速的最强指示是一个元素被应用了一个 3D 变换。
例如:
代码语言:javascript复制.box {
-webkit-transform: translate3d(250px,250px,250px)
rotate3d(250px,250px,250px,-120deg)
scale3d(0.5, 0.5, 0.5);
}
使用
只需要在你想要加速的元素上添加一个属性:transform: translateZ(0);
或者 transform: translate3d(0,0,0);
。
这种是最简单的诱骗浏览器开启 GPU 加速的方法。
这样就可以强制浏览器使用 GPU 来渲染这个元素,而不是 CPU。
当然,你也可以添加其他的 transform
属性,比如旋转,缩放,倾斜等,只要有一个 Z 轴的变化就可以触发 GPU 加速。
如果用 Tailwind CSS 的话,官方就有 GPU 加速的玩法,直接加一个 transform-gpu
。
补充
以下属性都可以触发 GPU 加速:
代码语言:javascript复制transform
opacity
filter
will-change
至于 will-change
这个东西,感觉说法很模糊:
提前告诉浏览器可能会变化的元素,这样,浏览器就可以为这个元素做一些优化,比如分配更多的资源,创建一个新的图层,或者启用 GPU 加速。
感觉具体是当你使用 will-change
时,浏览器会把你的元素放到一个新的合成层(composite layer)上。
合成层是一个可以被 GPU 处理的图层。当你对这个元素进行变化时,浏览器就会让 GPU 来更新合成层上的位图。
示例
再来一个简单的示例。 示例 1:一个简单的旋转动画,没有使用 GPU 加速。
代码语言:javascript复制<div class="box"></div>
<style>
.box {
width: 200px;
height: 200px;
background: linear-gradient(to right, pink, purple);
margin: 50px auto;
animation: spin 3s infinite linear;
}
@keyframes spin {
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}
</style>
示例 2:一个简单的旋转动画,使用了 GPU 加速。
代码语言:javascript复制<div class="box"></div>
<style>
.box {
width: 200px;
height: 200px;
background: linear-gradient(to right, pink, purple);
margin: 50px auto;
animation: spin 3s infinite linear;
}
@keyframes spin {
from {transform: rotate(0deg) translateZ(0);}
to {transform: rotate(360deg) translateZ(0);}
}
</style>
后记
不建议乱用,现在设备性能过剩,其实不用太担心卡顿问题。 每个都 GPU 拉满的话没必要,而且耗电吃内存。
除非你遇到比我学校机房电脑还逆天的机器。