主页关于链接归档灯泡

CSS 强制启用 GPU 加速

代码

最近在学校机房上前端课,用到了之前偶然看到的 CSS 的 GPU 渲染,性能肉眼可见提升。


前言

上课摸鱼整了个背景变色动画玩,发现卡到起飞,感觉帧数不到 10。开下任务管理器发现 CPU 满了,GPU 大概跑了一半。
试着用了所谓的“GPU 加速”后,情况改善不少,虽然还是远没有到达 30 帧。

在这机房上课真的折磨。

原理

CSS 的动画,变换和过渡并不会自动启用 GPU 加速,而是使用浏览器更慢的软件渲染引擎执行。
而许多浏览器提供了使用某些CSS规则的时候开启 GPU 加速渲染的功能。

主流的,像 Chrome、FireFox、Edge 和 Safari 这样的浏览器都支持硬件加速。

在 CSS 中,加速的最强指示是一个元素被应用了一个 3D 变换。

例如:

.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 加速:

transform
opacity
filter
will-change

至于 will-change 这个东西,感觉说法很模糊:

提前告诉浏览器可能会变化的元素,这样,浏览器就可以为这个元素做一些优化,比如分配更多的资源,创建一个新的图层,或者启用 GPU 加速。

感觉具体是当你使用 will-change 时,浏览器会把你的元素放到一个新的合成层(composite layer)上。
合成层是一个可以被 GPU 处理的图层。当你对这个元素进行变化时,浏览器就会让 GPU 来更新合成层上的位图。

示例

再来一个简单的示例。
示例 1:一个简单的旋转动画,没有使用 GPU 加速。

<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 加速。

<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 拉满的话没必要,而且耗电吃内存。

除非你遇到比我学校机房电脑还逆天的机器。

参考

the end.