requestAnimationFrame (rAF)

Браузер вызывает callback перед каждой перерисовкой — основа плавной анимации.

Что это

requestAnimationFrame(callback) ставит коллбек в очередь к следующему кадру (обычно 60 FPS — каждые ~16.7ms; на high-refresh дисплеях — 120/144 Hz). Получает аргументом DOMHighResTimeStamp — высокоточное время старта кадра. Отменяется через cancelAnimationFrame(id).

Базовое использование

let id;

function tick(timestamp) {
  // timestamp — мс с начала навигации, делишь на 1000 → секунды
  car.style.transform = `translateX(${pos}px)`;
  pos += 2;

  if (pos < 800) {
    id = requestAnimationFrame(tick);
  }
}

id = requestAnimationFrame(tick);
// cancelAnimationFrame(id); // остановить

// С известным временем (delta-based анимация — независима от FPS)
let lastTime = performance.now();
function animate(now) {
  const dt = (now - lastTime) / 1000; // сек
  lastTime = now;
  player.x += player.vx * dt;
  requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

Поддержка

Все браузеры, Node.js (нет, это браузерный API). Подменяется в тестах через jsdom или polyfill setTimeout(fn, 16).

Свойства

  • Пауза на скрытой вкладке (document.hidden) → троттлинг до 1Hz или вообще пауза
  • Синхронизирован с display refresh (нет лишних кадров)
  • Вызывается ДО layout/paint → правильное место для изменения стилей
  • Не накапливается в очереди при тормозах (в отличие от setInterval)

Подводные камни

  • НЕ для регулярных задач — для них setInterval/setTimeout
  • На фоновой вкладке таймер замирает → длительность анимации не равна wall-clock
  • Анимация по «шагам» (+1px за кадр) ломается на 120 Hz — используй delta-time через timestamp
  • Долгая работа в коллбеке роняет FPS → выноси в Web Workers или режь на чанки
  • Один кадр → один rAF. Множественные вызовы в одном кадре батчатся

Используется в bootcamp

  • AsyncRace — анимация движения машинок: каждый кадр пересчитывать transform: translateX(...) от скорости/времени
  • Podcast Player / Video Player — плавный прогресс-бар вместо рывков timeupdate (~4Hz)
  • Любая JS-анимация, где нельзя обойтись CSS transitions

Ссылки

См. также