requestAnimationFrame: движение по времени кадра
RequestAnimationFrame вызывает функцию перед подходящей отрисовкой браузера. Для движения нужно учитывать прошедшее время, а не добавлять одинаковое расстояние на каждом кадре.
Назначение
RequestAnimationFrame вызывает функцию перед подходящей отрисовкой браузера. Для движения нужно учитывать прошедшее время, а не добавлять одинаковое расстояние на каждом кадре.
Как это работает
В собственной странице создайте небольшой блок id frame-demo с запасом места справа. Пример двигает его на 60 пикселей за 600 миллисекунд. Предпочтение уменьшенного движения проверяется перед запуском.
Пример
const element = document.querySelector("#frame-demo");
let frame = null;
let start;
function draw(time) {
if (start === undefined) start = time;
const progress = Math.min((time - start) / 600, 1);
element.style.transform = `translateX(${60 * progress}px)`;
frame = progress < 1 ? requestAnimationFrame(draw) : null;
}
if (!matchMedia("(prefers-reduced-motion: reduce)").matches) {
frame = requestAnimationFrame(draw);
}
function stopDemo() {
if (frame !== null) cancelAnimationFrame(frame);
frame = null;
}
Что должно получиться
Положение зависит от временной метки callback, поэтому частота экрана не задаёт скорость напрямую. При reduced-motion начальный запуск пропускается. StopDemo отменяет следующий ожидающий кадр.
Граница применения и частая ошибка
В фоновой вкладке кадры обычно приостанавливаются; это не таймер для обязательной серверной работы. Код проверяет настройку движения только в начале — рабочий компонент должен учитывать её изменение. Для простой CSS-анимации JavaScript может быть избыточным.
Самостоятельная проверка
Сравните обычный режим и уменьшенное движение. Остановите пример до завершения и проверьте, что кадры не продолжаются. Затем переключите вкладку во время анимации и объясните возможный скачок прогресса по времени.