Руководство по requestAnimationFrame ()

Изучите API, чтобы выполнять анимацию и планировать события предсказуемым образом

requestAnimationFrame()- относительно недавний API-интерфейс браузера. Это дает более предсказуемый способ подключиться к циклу рендеринга браузера.

В настоящее время поддерживается всеми современными браузерами (и IE 10+).

Browser support

Это не API, специфичный для анимации, но именно там он используется чаще всего.

В JavaScript есть цикл событий. Он постоянно запускается для выполнения JavaScript.

Раньше анимация выполнялась с использованиемsetTimeout()или жеsetInterval(). Вы выполняете небольшую анимацию и вызываетеsetTimeout()чтобы снова повторить этот код через несколько миллисекунд:

const performAnimation = () => {
  //...
  setTimeout(performAnimation, 1000 / 60)
}
setTimeout(performAnimation, 1000 / 60)

или же

const performAnimation = () => {
  //...
}
setInterval(performAnimation, 1000 / 60)

Вы можете остановить анимацию, получив ссылку на тайм-аут или интервал и очистив ее:

let timer

const performAnimation = () => { //… timer = setTimeout(performAnimation, 1000 / 60) }

timer = setTimeout(performAnimation, 1000 / 60)

//… clearTimeout(timer)

В1000 / 60интервал междуperformAnimation()Количество вызовов определяется частотой обновления монитора, которая в большинстве случаев составляет 60 Гц (60 перерисовок в секунду), поскольку выполнять перерисовку бесполезно, если монитор не может отображать ее из-за своих ограничений. Это приводит к ~ 16,6 мс времени, которое в нашем распоряжении есть для отображения каждого кадра.

Проблема с этим подходом заключается в том, что даже если мы точно укажем эту точность, браузер может быть занят выполнением других операций, и наши вызовы setTimeout могут не успеть к перерисовке, и это будет отложено до следующего цикла.

Это плохо, потому что мы теряем один кадр, а в следующем анимация выполняется 2 раза, из-за чего глаз замечает неуклюжую анимацию.

Проверьте этот пример на Glitch of anанимация построена с использованием setTimeout ().

requestAnimationFrame- это стандартный способ выполнения анимации, и он работает совершенно по-другому, событие, хотя код очень похож на код setTimeout / setInterval:

let request

const performAnimation = () => { request = requestAnimationFrame(performAnimation) //animate something }

requestAnimationFrame(performAnimation)

//… cancelAnimationFrame(request) //stop the animation

Этот пример на Glitch of anанимация построена с использованием requestAnimationFrame ()покажи покажи.

Оптимизация

requestAnimationFrame()так как его введение было очень дружелюбным к процессору, вызывая остановку анимации, если текущее окно или вкладка не видны.

В то время, когда был представлен requestAnimationFrame (), setTimeout / setInterval выполнялся, даже если вкладка была скрыта, но теперь, поскольку этот подход оказался успешным также для экономии заряда батареи, браузеры также реализовали дросселирование для этих событий, позволяя максимум 1 выполнение в секунду. .

С помощьюrequestAnimationFrameбраузер может дополнительно оптимизировать потребление ресурсов и сделать анимацию более плавной.

Примеры временной шкалы

Это идеальная временная шкала, если вы используете setTimeout или setInterval:

Perfect timeline

у вас есть набор событий рисования (зеленый) и рендеринга (фиолетовый), и ваш код находится в желтом поле - кстати, это цвета, которые используются в Browser DevTools, а также для представления временной шкалы:

The devtools timeline

На иллюстрации показан идеальный корпус. У вас есть рисование и рендеринг каждые 60 мс, а ваша анимация происходит между ними, совершенно регулярно.

Если вы использовали более частый вызов для своей функции анимации:

Too frequent timeline

Обратите внимание, как в каждом кадре мы вызываем 4 шага анимации до того, как произойдет какой-либо рендеринг, и это сделает анимацию очень прерывистой.

Что делать, если setTimeout не может работать вовремя из-за того, что другой код блокирует цикл событий? Получаем пропущенный кадр:

Missed frame

Что, если шаг анимации занимает немного больше времени, чем вы ожидаете?

Delay in the timeline

события рендеринга и рисования также будут отложены.

Вот какrequestAnimationFrame()работает визуально:

Delay in the timeline

весь код анимации запускаетсяпередсобытия рендеринга и рисования. Это делает код более предсказуемым, и у нас есть много времени, чтобы сделать анимацию, не беспокоясь о том, что время, которое у нас есть, превышает 16 мс.

Проверятьэто отличное видео Джейка Арчибальдапо теме.

Скачать мою бесплатнуюРуководство для начинающих по JavaScript


Больше руководств по браузеру: