Как поступает браузер если скорость анимации больше 60 fps?
Комментарии (4)
Ответ сгенерирован нейросетью и может содержать ошибки
Поведение браузера при скорости анимации выше 60 fps
Контекст: Display Refresh Rate
Ключевой момент: большинство мониторов имеют частоту обновления 60 Hz, что означает, что они могут отображать максимум 60 кадров в секунду (fps). Некоторые новые мониторы работают на 120 Hz, 144 Hz или даже 240 Hz.
Когда говорят "скорость анимации больше 60 fps", это значит, что браузер пытается рассчитать и отрендерить кадры быстрее, чем монитор может их отобразить.
Что происходит
Браузер не может отобразить больше кадров, чем позволяет монитор.
Это физическое ограничение, которое нельзя преодолеть только улучшением кода. Браузер синхронизирует отрисовку с вертикальной синхронизацией (V-Sync) монитора.
// Даже если ты попытаешься анимировать элемент 200 раз в секунду
setInterval(() => {
// обнови элемент
}, 5); // каждые 5 ms = 200 раз в секунду
// На мониторе 60 Hz будут видны только 60 кадров из 200 расчётов
// Остальные 140 вычислений потрачены впустую!
requestAnimationFrame — правильный подход
Вместо setInterval, браузер предоставляет requestAnimationFrame (rAF), который автоматически синхронизируется с частотой обновления монитора:
// Неправильно — может быть несинхронизировано
let progress = 0;
const animateWrong = setInterval(() => {
progress += 5;
element.style.left = progress + 'px';
if (progress >= 300) clearInterval(animateWrong);
}, 10);
// Правильно — синхронизировано с монитором (60 fps или 120 fps)
let progress = 0;
function animate() {
progress += 5;
element.style.left = progress + 'px';
if (progress < 300) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
requestAnimationFrame автоматически вызывает твой callback с частотой монитора:
- На мониторе 60 Hz -> 60 раз в секунду
- На мониторе 120 Hz -> 120 раз в секунду
- На мониторе 240 Hz -> 240 раз в секунду
CSS анимации и переходы
CSS анимации (@keyframes) и переходы (transition) также работают в синхронизации с браузером и оптимизированы для частоты монитора:
/* CSS автоматически адаптируется к частоте монитора */
.element {
transition: transform 1s ease-in-out;
}
.element:hover {
transform: translateX(100px);
}
Браузер автоматически распределяет кадры для гладкой анимации, независимо от того, 60 fps или 120 fps.
Производительность: Проблема и решение
Проблема: Если ты "тратишь вычисления" для невидимых кадров, это стоит энергии и тепла:
// Вычисляем 200 кадров в секунду, видим только 60
const expensiveAnimate = () => {
const complexCalculation = doExpensiveComputation();
updateDOM(complexCalculation);
};
setInterval(expensiveAnimate, 5); // 200 раз в секунду
Это особенно заметно на мобильных устройствах, где батарея разряжается быстрее.
Решение: Используй requestAnimationFrame и оптимизируй сами вычисления:
// Вычисляем только видимые кадры
const optimalAnimate = () => {
const complexCalculation = doExpensiveComputation();
updateDOM(complexCalculation);
};
requestAnimationFrame(optimalAnimate);
Дельта-время и временные интервалы
Для более сложных анимаций важно учитывать прошедшее время, так как частота монитора может отличаться:
let lastTime = performance.now();
let position = 0;
function animateWithDelta() {
const currentTime = performance.now();
const deltaTime = (currentTime - lastTime) / 1000; // в секундах
lastTime = currentTime;
// Движись на 100px в секунду (независимо от fps!)
position += 100 * deltaTime;
element.style.left = position + 'px';
if (position < 300) {
requestAnimationFrame(animateWithDelta);
}
}
requestAnimationFrame(animateWithDelta);
Так анимация будет одинаковой скоростью на мониторах 60 fps и 120 fps.
Web Animations API
Для сложных анимаций есть Web Animations API, который автоматически оптимизирует синхронизацию:
const animation = element.animate(
[
{ transform: 'translateX(0)', opacity: 1 },
{ transform: 'translateX(100px)', opacity: 0.5 }
],
{
duration: 1000,
easing: 'ease-in-out',
iterations: 1
}
);
// Браузер автоматически синхронизирует с монитором
Инструменты для анализа
- Chrome DevTools Performance tab — показывает частоту кадров и Frame Rate
- Chrome DevTools Rendering Settings — можно эмулировать разные частоты монитора
// Проверить текущую частоту монитора
const refreshRate = screen.webkitMatchMediaProperties?.[0]?.refresh || 60;
console.log(`Refresh rate: ${refreshRate} Hz`);
Выводы
- Браузер не может отобразить больше кадров, чем позволяет монитор — это физическое ограничение
- Используй requestAnimationFrame — автоматически синхронизируется с монитором
- CSS анимации оптимальны — браузер сам оптимизирует их для текущего монитора
- Учитывай дельта-время — для одинаковой скорости на разных мониторах
- Избегай лишних вычислений — каждый невидимый кадр потребляет ресурсы батареи
Главное: качество и гладкость анимации зависит не от того, насколько быстро ты пытаешься анимировать, а от того, насколько хорошо ты синхронизируешься с монитором пользователя.