如何将此 CSS 动画转换为使用 GPU 级别,而不是更新图层树

How to convert this CSS animation to use GPU level, instead of updating layer tree

我试图了解 CSS 对象的 fps 延迟。

我检查了我的时间轴,发现我写的这个动画在每个时间间隔都会导致图层树更新,这是正常的。

这个动画所做的只是扩展条的宽度。它一遍又一遍地重复,直到我的 JavaScript 从 HTML 元素(div 标记)中删除 class。

我如何将其转换为使用 GPU 层(复合层)或任何提高性能的技巧 (rendering/fps),因为它必须启动,而其他动画不在我通过外部控制的范围内内嵌框架。 YouTube html5 嵌入式播放器是其中之一。

有没有办法将其(设置条的宽度动画)转换为 GPU 层?我能以某种方式翻译它吗?还是有更好的?

有 3 个小节。这是它的动画,不是样式。

@keyframes color-bar {
  0%   { width:17px;  }
  10%  { width:11px;  }
  20%  { width:37px;  }
  30%  { width:30px;  }
  40%  { width:15px;  }
  50%  { width:10px;  }
  60%  { width:24px;  }
  70%  { width:17px;  }
  80%  { width:21px;  }
  90%  { width:32px;  }
  100% { width:17px;  }
}
.lines-ani {
    transform: rotateY(180deg);
}
.lines-ani .lines {
    animation: color-bar 1.5s 2s ease-out alternate infinite;
}
.lines-ani .lines:before {
    animation: color-bar 1.5s 1.5s ease-out alternate infinite;
}
.lines-ani .lines:after {
    animation: color-bar 1.5s 2.5s ease-out alternate infinite;
}

如果您想避免重新绘制并将动画移动到 GPU,那么您可以使用 3D 变换来产生效果,而不是对 width 进行动画处理。如 this article 中所述,使用 3D 变换意味着浏览器将使动画 GPU 加速。

CSS animations, transforms and transitions are not automatically GPU accelerated, and instead execute from the browser’s slower software rendering engine. So what exactly forces the browser to swap to GPU mode? Many browsers provide GPU acceleration by means of certain CSS rules.

Currently, browsers like Chrome, FireFox, Safari, IE9+ and the latest version of Opera all ship with hardware acceleration; they only use it when they have an indication that a DOM element would benefit from it. With CSS, the strongest indication is that a 3D transformation is being applied to an element.

将动画转换为等效的 3D 变换本身并不是一个大过程。只需要给三个元素都设置一个初始的width,然后根据设置的初始宽度,将@keyframes规则中的width转换成对应的比例值即可。

宽度动画通常只是 scaleX 但使用 scale3d 是因为我们需要将动画移动到 GPU。由于 scale3d 有 3 个参数(用于三个轴中每个轴的比例),我们可以提供 1(初始比例)作为其他两个轴的值。所以,它将是 scale3d(x ratio, 1, 1).

例如,问题中提供的 10% 框架具有 width: 11px 设置,以下是我们如何获得其等效的 scale3d 值:

  • 在元素上设置初始或开始 width。在下面的片段中,我将其设置为 17px。
  • 根据初始宽度和需要的宽度得到X轴的缩放比例。那就是 11px / 17px(即 0.64)。
  • 因此,等效的 3D 比例变换将是 scale3d(0.64, 1, 1)

@keyframes color-bar {
  0% {
    transform: scale3d(1,1,1);
  }
  10% {
    transform: scale3d(0.64,1,1);
  }
  20% {
    transform: scale3d(2.17,1,1);
  }
  30% {
    transform: scale3d(1.76,1,1);
  }
  40% {
    transform: scale3d(0.88,1,1);
  }
  50% {
    transform: scale3d(0.58,1,1);
  }
  60% {
    transform: scale3d(1.41,1,1);
  }
  70% {
    transform: scale3d(1,1,1);
  }
  80% {
    transform: scale3d(1.23,1,1);
  }
  90% {
    transform: scale3d(1.88,1,1);
  }
  100% {
    transform: scale3d(1,1,1);
  }
}
.lines-ani {
  width: 25vw;
  transform: rotateY(180deg);
}
.lines-ani .lines {
  position: relative;
  width: 17px;
  height: 10px;
  background: red;
  transform-origin: left;
  animation: color-bar 1.5s 2s ease-out alternate infinite;
}
.lines-ani .lines:before {
  position: absolute;
  content: '';
  top: 125%;
  height: 100%;
  width: 100%;
  background: green;
  transform-origin: left;
  animation: color-bar 1.5s 1.5s ease-out alternate infinite;
}
.lines-ani .lines:after {
  position: absolute;
  content: '';
  top: 250%;
  height: 100%;
  width: 100%;
  background: green;
  transform-origin: left;
  animation: color-bar 1.5s 2.5s ease-out alternate infinite;
}
<div class='lines-ani'>
  <div class='lines'>
  </div>
</div>

注意: 如果您不想使用 scale3d,您也可以使用 scaleX() translateZ(0)translateZ(0) 是一个 3D 变换,整个过程仍然会产生相同的效果。