На анимацию, связанную с GPU, все еще влияет загрузка процессора? - PullRequest
0 голосов
/ 08 января 2019

Я создал композитный слой для div со следующими стилями:

div {
  position: absolute;
  height: 50px;
  width: 50px;
  background: #900;
  top: 100px;
  left: 200px;
  will-change: transform;
  transform: translateZ(0);
}

Затем я применяю к нему анимацию с помощью API веб-анимации:

document.getElementById("box").animate(
  [
    { transform: 'rotate(0) translate3D(-50%, -50%, 0)' },
    { transform: 'rotate(360deg) translate3D(-50%, -50%, 0)' }
  ], {
    duration: 500,
    iterations: Infinity
  }
);

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

Чего я не понимаю, так это того, что если я вызову функцию с интенсивным использованием процессора, анимация полностью остановится во время работы функции и возобновит работу при выходе из функции:

function mySlowFunction(baseNumber) {
    console.time('mySlowFunction');
    var result = 0; 
    for (var i = Math.pow(baseNumber, 10); i >= 0; i--) {       
        result += Math.atan(i) * Math.tan(i);
    };
    console.timeEnd('mySlowFunction');
    return result;
}

setTimeout(() => mySlowFunction(5), 3000);

Есть ли способ предотвратить это?

https://jsfiddle.net/Lsmw85rv/4/

1 Ответ

0 голосов
/ 08 января 2019

Да, они все еще могут зависеть от загрузки процессора.
обновление алгоритма рендеринга является частью цикла событий, поэтому, если каким-то образом вы блокируете цикл событий, вы также блокируете рендеринг.

Теперь разработчикам рекомендуется "вращать цикл событий" , когда они встречают долго работающий код, чтобы пользовательский интерфейс мог все еще быть реактивным (и анимации без поддержки js могут продолжать работать), но это это просто поощрение, и все реализации не делают это одинаково.

Например, на моем Firefox я не вижу замедления ни в вашем скрипте, ни даже в более агрессивном ниже, в то время как в моем Chrome я четко вижу, что рендеринг заблокирован.

Теперь, чтобы избежать этого, как было сказано в комментарии, реальным пуленепробиваемым решением было бы запустить сценарий блокировки во втором потоке с помощью веб-рабочего .

document.getElementById("box").animate(
  [{
      transform: 'rotate(0) translate3D(-50%, -50%, 0)'
    },
    {
      transform: 'rotate(360deg) translate3D(-50%, -50%, 0)'
    }
  ], {
    duration: 500,
    iterations: Infinity
  }
);

function mySlowFunction(baseNumber) {
  console.time('mySlowFunction');
  const now = performance.now();
  while (performance.now() - now < baseNumber * 1000);
  console.timeEnd('mySlowFunction');
}

setTimeout(() => mySlowFunction(3), 3000);
#box {
  position: absolute;
  height: 50px;
  width: 50px;
  background: #900;
  top: 100px;
  left: 200px;
  will-change: transform;
  transform: translateZ(0);
}
<div id="box"></div>
...