Що робить requestAnimationFrame()?
Визначення
requestAnimationFrame(callback) - це вбудований API браузера,
який запланує виконання функції callback перед наступним кадром відмальовування (перед "перемальовуванням екрана").
Що це означає на практиці
Коли браузер збирається перемалювати екран (зазвичай ~60 разів на секунду, тобто кожні 16.6 мс),
він викликає твій колбек з requestAnimationFrame в оптимальний момент,
щоб анімація виглядала максимально плавною і без ривків.
Приклад
function animate(time) {
console.log('Кадр в', time, 'мс');
requestAnimationFrame(animate); // запитуємо наступний кадр
}
requestAnimationFrame(animate);Що відбувається:
animateвикликається перед кожним кадром відмальовування;time- це timestamp (у мілісекундах), який показує, коли саме почалося відмальовування кадру (заperformance.now()).
Як це працює під капотом
- Ти викликаєш
requestAnimationFrame(fn); - Функція
fnзберігається браузером; - Коли браузер готовий малювати новий кадр (зазвичай через 16 мс), він перед перемальовуванням викликає всі такі функції;
- Після виклику колбека браузер перемальовує екран.
Якщо всередині колбека знову викликати requestAnimationFrame(),
анімація йтиме в циклі - кадр за кадром.
Приклад плавного руху елемента
const box = document.querySelector('.box');
let start = null;
function move(timestamp) {
if (!start) start = timestamp;
const progress = timestamp - start;
box.style.transform = `translateX(${progress / 5}px)`;
if (progress < 2000) { // 2 секунди
requestAnimationFrame(move);
}
}
requestAnimationFrame(move);Тут елемент плавно переміщується протягом 2 секунд.
А браузер сам оптимізує виклики - якщо вкладка не видна,
requestAnimationFrame призупиняється, щоб не витрачати ресурси.
Відмінність від setTimeout / setInterval
| Критерій | setTimeout / setInterval | requestAnimationFrame |
|---|---|---|
| Частота | Фіксована (наприклад, кожні 16 мс) | Синхронізується з частотою оновлення екрана |
| Енергоспоживання | Не призупиняються у вкладках | Автоматично зупиняється, якщо вкладка прихована |
| Плавність | Може "рватися" при навантаженні | Максимально плавне відмальовування |
| Використання | Таймери, фонові задачі | Анімації, плавні оновлення UI |
| Передає timestamp | Ні | Так (performance.now() час кадру) |
Приклад порівняння
function moveWithTimeout() {
box.style.left = `${parseInt(box.style.left || 0) + 1}px`;
setTimeout(moveWithTimeout, 16);
}
function moveWithRaf() {
box.style.left = `${parseInt(box.style.left || 0) + 1}px`;
requestAnimationFrame(moveWithRaf);
}setTimeout не враховує навантаження браузера, може "проскакувати" кадри.
requestAnimationFrame підлаштовується під частоту дисплея і завжди максимально плавний.
Скасування виклику
Якщо потрібно скасувати запланований кадр:
const id = requestAnimationFrame(step);
cancelAnimationFrame(id);ПІДСУМОК
| Властивість | Опис |
|---|---|
| Що робить | Запускає колбек перед наступним кадром відмальовування |
| Коли викликається | Коли браузер готовий намалювати новий кадр (~60 FPS) |
| Аргумент функції | timestamp - час початку кадру |
| Повертає | ID кадру (для cancelAnimationFrame) |
| Зупиняється автоматично | Так, якщо вкладка неактивна |
| Тип задачі | Окрема черга для візуальних оновлень (до рендера) |
| Ідеально підходить для | Анімацій, плавних трансформацій, прогрес-барів |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.