Что такое requestAnimationFrame и зачем он нужен в анимациях?
Что проверяют
Понимаете ли вы, что анимацию надо синхронизировать с перерисовкой экрана, и знаете ли, чем плох таймер.
Как отвечать
requestAnimationFrame просит браузер выполнить функцию перед следующей отрисовкой кадра. Вызов однократный, поэтому для непрерывной анимации внутри обработчика запрашивают следующий кадр:
function step(time) {
el.style.transform = `translateX(${time / 10}px)`;
requestAnimationFrame(step);
}
requestAnimationFrame(step);Чем это лучше setInterval(fn, 16):
- синхронизация с частотой обновления экрана. Таймер не знает о кадрах: часть вызовов попадёт между отрисовками и пропадёт впустую, часть кадров останется без обновления. Получается дёрганое движение, хотя в среднем частота верная. На экране с частотой 120 Гц таймер на 16 мс вдвое отстанет от возможностей;
- браузер приостанавливает анимацию в неактивной вкладке, экономя батарею. Таймер продолжает работать вхолостую, а при возврате на вкладку накопленные вызовы дают скачок;
- в колбэк приходит точное время кадра, и движение считают от него, а не от номера кадра. Тогда скорость не зависит от частоты экрана и от пропущенных кадров;
- вызовы группируются: все изменения происходят в одной точке перед отрисовкой.
Отменяют через cancelAnimationFrame по идентификатору, и это обязательно при размонтировании компонента.
Важная оговорка: если анимацию можно описать в CSS (transition, animation), лучше так. Анимация transform и opacity выполняется в потоке композиции и не зависит от занятости основного потока, а requestAnimationFrame выполняется как раз в нём и встанет вместе с ним. JavaScript берут там, где нужен расчёт, физика или реакция на данные.
И правило внутри кадра: сначала все чтения геометрии, потом все записи. Чередование offsetHeight и присваивания стиля вызывает принудительный пересчёт разметки на каждой итерации.
Где спотыкаются
Считают шаг анимации по числу кадров, а не по времени.
Не отменяют кадр при размонтировании.
Анимируют left и top вместо transform.
Чередуют чтение и запись стилей внутри одного кадра.