requestAnimationFrame — это встроенный механизм браузера
для выполнения анимаций, синхронизированных с частотой обновления
экрана. В отличие от setTimeout и setInterval,
он учитывает производительность системы и приостанавливается, если
вкладка неактивна.
Ключевые особенности:
Пример базового использования:
function animate(time) {
// time — время с начала работы requestAnimationFrame
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
requestAnimationFrame в anime.jsБиблиотека anime.js полностью опирается на
requestAnimationFrame для управления анимациями. Это
означает:
Внутри anime.js создаётся собственный цикл рендеринга, который:
anime.js реализует централизованный движок, который можно условно представить следующим образом:
let activeAnimations = [];
function engine(time) {
for (let i = 0; i < activeAnimations.length; i++) {
activeAnimations[i].tick(time);
}
if (activeAnimations.length > 0) {
requestAnimationFrame(engine);
}
}
Каждая анимация регистрируется в общем массиве и обновляется на каждом кадре.
Использование одного requestAnimationFrame-цикла
позволяет:
Пример:
anime({
targets: '.box',
translateX: 250,
duration: 2000
});
anime({
targets: '.circle',
translateY: 150,
duration: 2000
});
Обе анимации выполняются в одном цикле и обновляются одновременно.
anime.js использует время, переданное в
requestAnimationFrame, для вычисления прогресса
анимации:
progress = (currentTime - startTime) / duration;
Это обеспечивает:
Хотя requestAnimationFrame стремится к ~60 FPS,
фактическое значение зависит от:
anime.js компенсирует это за счёт:
При переключении вкладки браузер автоматически приостанавливает
requestAnimationFrame. anime.js корректно обрабатывает
это:
Пример логики:
if (document.hidden) {
// приостановка обновлений
}
Синхронизация через requestAnimationFrame позволяет:
Минимизировать перерисовки:
Избегать layout thrashing:
Использовать GPU-ускорение:
transform, opacity)
обновляются эффективноanime.js позволяет интегрироваться с внешними циклами:
anime.running.forEach(anim => anim.pause());
function customLoop(time) {
anime.running.forEach(anim => anim.tick(time));
requestAnimationFrame(customLoop);
}
requestAnimationFrame(customLoop);
Это полезно при:
Таймлайны в anime.js также используют общий
requestAnimationFrame:
let timeline = anime.timeline();
timeline
.add({
targets: '.box',
translateX: 200
})
.add({
targets: '.box',
translateY: 200
});
Каждый шаг таймлайна рассчитывается в рамках одного цикла, что гарантирует:
anime.js поддерживает глобальный контроль времени:
anime.speed = 0.5;
Это влияет на все анимации, так как:
requestAnimationFrameЕсли кадры пропускаются (например, из-за нагрузки), anime.js:
Это предотвращает:
| Подход | Особенности |
|---|---|
setInterval |
фиксированный интервал, не синхронизирован с рендерингом |
setTimeout |
нет гарантии точного времени |
requestAnimationFrame |
синхронизация с экраном, оптимизация браузером |
anime.js использует исключительно requestAnimationFrame,
избегая недостатков альтернатив.
Несмотря на преимущества, существуют ограничения:
requestAnimationFrame работает на уровне браузерного
рендеринга:
requestAnimationFrameanime.js вставляется в этот цикл перед перерисовкой, что обеспечивает: