css 为什么一个简单的过渡会耗费如此多的GPU资源?

lkaoscv7  于 2023-03-25  发布在  其他
关注(0)|答案(2)|浏览(119)

我正在开发一个简单的音乐播放器。我注意到的一件事是,尽管实际的布局非常简单,但GPU的使用率却高得不合理。在禁用页面的各种元素后,我意识到进度条转换是导致这种大量GPU使用的原因。

这很奇怪,因为它看起来很简单。即使我在Codepen中完成,它也会导致大量的GPU使用:
https://jsfiddle.net/bhn9sfux/

let progressBar = document.getElementById("progressbar");
setTimeout(() => progressBar.style.width = "100%", 1000);
#progressbar {
  background: black;
  height: 10px;
  width: 0;
  transition: width 60s linear;
}
<div id="progressbar"></div>

我的电脑相当结实(RX Vega 56),显然它仍然可以流畅地显示它。这不是问题所在。让我困惑的是,这样一个简单的转换怎么会导致如此大的性能消耗。我期待的是低0点数字,绝对没有“中等”水平的功耗。
我的CSS是不是很糟糕?我是不是忽略了渲染引擎的一些东西?或者仅仅是它本来的样子?

j0pj023g

j0pj023g1#

它消耗这么多GPU的原因是因为你正在动画width属性。当你改变一个影响盒子尺寸的值时,(以及一些其他属性)DOM需要重新运行一系列计算,这会导致DOM的完全回流。这是相当昂贵的。

根据定义,“回流”是Web浏览器用来重新计算文档中元素的位置和几何形状的过程。它基本上是浏览器在每次发生更改时(无论是刷新,屏幕调整大小还是常见的显示/隐藏内容操作)都需要做的工作,以定位屏幕中的每个元素。
尝试使用类似clip-path的动画,或者使用overflow: hidden;将进度条 Package 在父容器中,然后使用transform: translate3d();移动进度条。

下面是一个使用clip-path的简单示例:

.bar {
  background: red;
  height: 50px;
  width: 500px;
  animation: 1s infinite alternate slidein;
  clip-path: inset(0 100% 0 0);
}

@keyframes slidein {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}
<div class="bar"></div>
i2byvkas

i2byvkas2#

如果你想减少GPU的使用,你可以尝试CSS的will-change属性,或者使用requestAnimationFrame这个方法可以帮助同步渲染与浏览器的内部动画循环,这可以提高性能并减少GPU的使用。我所看到的不是你的代码或进度条,而是SetTimeout()。

相关问题