Низкая производительность CSS-анимации - браузер не разрисовывает

У меня есть несколько элементов, которые я анимирую, и которые я разработал таким образом, чтобы они не появлялись в браузере. Если я включаю «Мигание краски» в Chrome Devtools, я вообще не вижу мигания краски. Однако, если я записываю производительность, то график показывает, что на рисование тратится много времени. Время от времени FPS составляет всего 15 кадров в секунду.

На самом деле я построил это во 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);
  }
}
<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>
За пределами сигналов Angular: Сигналы и пользовательские стратегии рендеринга
За пределами сигналов Angular: Сигналы и пользовательские стратегии рендеринга
TL;DR: Angular Signals может облегчить отслеживание всех выражений в представлении (Component или EmbeddedView) и планирование пользовательских...
Sniper-CSS, избегайте неиспользуемых стилей
Sniper-CSS, избегайте неиспользуемых стилей
Это краткое руководство, в котором я хочу поделиться тем, как я перешел от 212 кБ CSS к 32,1 кБ (сокращение кода на 84,91%), по-прежнему используя...
3
0
104
1

Ответы 1

Похоже, что вся работа велась на Composite Layers, и не обязательно только на Painting. Я обнаружил, что добавление transform: translateZ(0) или will-change к отдельным анимированным элементам не очень помогает. Однако, если я добавлю transform: translateZ(0) к родительскому элементу .circle, то время, потраченное на Composite Layers и Painting, значительно сократится.

Он по-прежнему работает довольно медленно, но я думаю, что это может быть просто потому, что на моем компьютере есть встроенная графика и 4 ГБ оперативной памяти.

Так что я думаю, что это так хорошо, насколько это возможно, но был бы признателен за любые дальнейшие предложения.

Вот пример, в котором я добавил transform: translateZ(0) к родительскому элементу:

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

РЕДАКТИРОВАТЬ:

Я обнаружил значительное улучшение, удалив border-radius на родительском элементе, который я установил на overflow: hidden для создания маски:

Перед:

.circle {
  border-radius: 50%;
  overflow: hidden;
}

Вместо этого я использовал clip-path в качестве маски:

После

  transform: translateZ(0);
  clip-path: circle(49% at 50% 50%);

Я уверен, вы сразу заметите, что это намного лучше:

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

Мы будем очень признательны за любое дальнейшее понимание того, почему это работает.

Другие вопросы по теме