糟糕的 CSS 动画性能 - 没有浏览器绘制

IOI*_*OIO 3 performance animation css-animations

我有许多正在制作动画的元素,我以一种不会导致任何浏览器绘制的方式开发这些元素。如果我在 Chrome Devtools 中打开“Paint Flashing”,我根本看不到任何油漆闪烁。但是,如果我记录表演,那么图表显示有很多时间花在绘画上。FPS 有时低至 15fps。

我实际上是在 Vue 中构建的,编译后的代码导致代码过多,无法粘贴到此处。我意识到动画有点坏了,我仍然需要计算一些时间等等 - 但就这个问题而言,我只关心性能。

我已经在 CodePen 上发布了编译后的代码:

https://codepen.io/IOIIOOIO/pen/gjBqyg

似乎 StackOverflow 要求我在这里发布一些代码,所以这里是只有一个元素的编译代码:

.circle {
  position: relative;
  width: 100%;
  padding-top: 100%;
  border-radius: 50%;
  overflow: hidden;
}

.circle::before {
    content: "";
    background-color: black;
    position: absolute;
    top: 0;
    left: 0;
    width: 50%;
    height: 100%;
    animation-name: switch;
    animation-iteration-count: infinite;
    animation-timing-function: steps(1);
    animation-duration: 3s;
    animation-delay: inherit;
  }

.rotating-circle {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
}

.rotating-circle--first-cycle {
    background-color: black;
    animation-name: rotate, toggle-first;
    animation-duration: 3s, 3s;
    animation-iteration-count: infinite, infinite;
    animation-timing-function: linear, steps(1);
    animation-delay: 1800ms;
  }

.rotating-circle--second-cycle {
    opacity: 0;
    animation-name: rotate, toggle-second;
    animation-duration: 3s, 3s;
    animation-iteration-count: infinite, infinite;
    animation-timing-function: linear, steps(1);
    animation-delay: 1800ms;
  }


@keyframes rotate {
  0% {
    transform: rotate3d(0, 1, 0, 0deg);
  }
  50% {
    transform: rotate3d(0, 1, 0, 180deg);
  }
}

@keyframes toggle-first {
  0% {
    opacity: 1;
  }
  25% {
    opacity: 0;
  }
  75% {
    opacity: 1;
  }
}

@keyframes toggle-second {
  0% {
    opacity: 0;
  }
  25% {
    opacity: 1;
  }
  75% {
    opacity: 0;
  }
}

@keyframes switch {
  0% {
    transform: translatex(0);
  }
  50% {
    transform: translatex(100%);
  }
  100% {
    transform: translatex(0);
  }
}
Run Code Online (Sandbox Code Playgroud)
<div class="circle" style="background-color: rgb(255, 0, 0); animation-delay: 0ms;">
  <div class="rotating-circle rotating-circle--first-cycle" style="animation-delay: 0ms;">
  </div>
  <div class="rotating-circle rotating-circle--second-cycle" style="background-color: rgb(255, 0, 0); animation-delay: 0ms;">
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

IOI*_*OIO 5

似乎所有的工作都是在 上完成的Composite Layers,而不一定是Painting单独完成的。我发现添加transform: translateZ(0)或添加will-change到正在动画中的单个元素并没有多大帮助。但是,如果我添加transform: translateZ(0)到父.circle元素,那么花费在Composite Layers和上的时间Painting就会大大减少。

它仍然运行得很慢,但我认为这可能只是因为我的电脑有板载显卡和 4GB 内存。

所以我认为这是最好的,但希望得到任何进一步的建议。

这是我添加transform: translateZ(0)到父元素的示例:

https://codepen.io/IOIIOOIO/pen/gjBqyg

编辑

我发现通过删除有显着的改进 border-radius父级,,我已经设置overflow: hidden为创建一个掩码:

前:

.circle {
  border-radius: 50%;
  overflow: hidden;
}
Run Code Online (Sandbox Code Playgroud)

相反,我使用剪辑路径作为掩码:

  transform: translateZ(0);
  clip-path: circle(49% at 50% 50%);
Run Code Online (Sandbox Code Playgroud)

我相信你会立即注意到它要好得多:

https://codepen.io/IOIIOOIO/pen/OwBBJV

任何进一步了解为什么这有效将不胜感激。