Spec-Zone.ru › Web APIs

Окно: метод requestAnimationFrame()

Базовая Широко поддерживается

Эта функция хорошо отработана и работает на многих устройствах и версиях браузеров. Она доступна во всех браузерах с июля 2015 года.

  • Подробнее
  • Полная совместимость
  • Отправить отзыв

Метод window.requestAnimationFrame() сообщает браузеру о желании выполнить анимацию. Он запрашивает у браузера вызов предоставленной пользователем функции обратного вызова перед следующим перерисовыванием.

Частота вызовов функции обратного вызова, как правило, соответствует частоте обновления дисплея. Наиболее распространённая частота обновления — 60 Гц (60 циклов/кадров в секунду), хотя также широко используются 75 Гц, 120 Гц и 144 Гц. requestAnimationFrame() вызовы в большинстве браузеров приостанавливаются при работе в фоновых вкладках или скрытых <iframe>, чтобы улучшить производительность и время автономной работы.

Примечание: Ваша функция обратного вызова должна снова вызвать requestAnimationFrame(), если вы хотите анимировать ещё один кадр. requestAnimationFrame() является одноразовой.

Предупреждение: Всегда используйте первый аргумент (или другой способ получения текущего времени) для расчёта того, насколько анимация будет продвигаться в кадре — в противном случае анимация будет работать быстрее на экранах с высокой частотой обновления. Способы сделать это см. в примерах ниже.

Синтаксис

requestAnimationFrame(callback)

Параметры

callback

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

timestamp

DOMHighResTimeStamp, указывающий конечное время рендеринга предыдущего кадра (основанное на количестве миллисекунд с момента начала отсчёта). Значение timestamp — это десятичное число в миллисекундах, но с минимальной точностью в 1 миллисекунду. Для Window объектов (не Workers), оно равно document.timeline.currentTime. Это значение timestamp совместно используется между всеми окнами, работающими на одном агенте (все окна с одинаковым происхождением и, что более важно, фреймы с одинаковым происхождением) — что позволяет синхронизировать анимации в нескольких requestAnimationFrame вызовах. Значение timestamp также подобно вызову performance.now() в начале функции обратного вызова, но оно никогда не будет иметь то же самое значение.

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

Возвращаемое значение

Целое число unsigned long, идентификатор запроса, уникально идентифицирующий запись в списке обратных вызовов. Вы не должны делать никаких предположений относительно его значения. Вы можете передать это значение в window.cancelAnimationFrame() для отмены запроса обратного вызова.

Предупреждение: Идентификатор запроса обычно реализуется как счётчик, инкрементируемый для каждого окна. Поэтому, даже если он начинает счёт с 1, он может переполниться и в конечном итоге достигнуть 0. Хотя для кратковременных приложений это маловероятно, вы не должны использовать 0 в качестве контрольного значения для недействительных идентификаторов запросов и вместо этого предпочитайте недостижимые значения, такие как null. Спецификация не указывает поведение при переполнении, поэтому поведение браузеров различается. При переполнении значение либо зацикливается на 0, либо принимает отрицательное значение, либо возникает ошибка. Если переполнение не вызывает ошибку, идентификаторы запросов также не являются строго уникальными, так как существует лишь конечное число 32-битных целых чисел для, возможно, бесконечного числа обратных вызовов. Обратите внимание, что, однако, возникновение проблемы займёт приблизительно 500 дней при отображении с частотой 60 Гц при 100 вызовах requestAnimationFrame() в кадр.

Примеры

В этом примере элемент анимируется в течение 2 секунд (2000 миллисекунд). Элемент перемещается со скоростью 0,1 пикселя/мс вправо, поэтому его относительное положение (в пикселях CSS) может быть вычислено в зависимости от времени, прошедшего с момента начала анимации (в миллисекундах) с помощью 0.1 * elapsed. Конечное положение элемента составляет 200 пикселей (0.1 * 2000) вправо от его начального положения.

const element = document.getElementById("some-element-you-want-to-animate");
let start;

function step(timestamp) {
  if (start === undefined) {
    start = timestamp;
  }
  const elapsed = timestamp - start;

  // Math.min() is used here to make sure the element stops at exactly 200px
  const shift = Math.min(0.1 * elapsed, 200);
  element.style.transform = `translateX(${shift}px)`;
  if (shift < 200) {
    requestAnimationFrame(step);
  }
}

requestAnimationFrame(step);

Следующие три примера иллюстрируют различные подходы к установлению нулевой точки во времени, основы для вычисления прогресса вашей анимации в каждом кадре. Если вы хотите синхронизироваться с внешними часами, такими как BaseAudioContext.currentTime, максимальная точность — длительность одного кадра, 16,67 мс при 60 Гц. Аргумент timestamp обратного вызова представляет собой конец предыдущего кадра, поэтому раньше, чем через кадр, ваши недавно вычисленные значения не будут отрисованы.

В этом примере ожидание до первого вызова обратного вызова для установки zero. Если ваша анимация переходит к новому значению при запуске, вы должны организовать её таким образом. Если вам не нужно синхронизироваться ни с чем внешним, например, с аудио, то этот подход рекомендуется, так как у некоторых браузеров есть задержка в несколько кадров между первоначальным вызовом requestAnimationFrame() и первым вызовом функции обратного вызова.

let zero;
requestAnimationFrame(firstFrame);
function firstFrame(timestamp) {
  zero = timestamp;
  animate(timestamp);
}
function animate(timestamp) {
  const value = (timestamp - zero) / duration;
  if (value < 1) {
    element.style.opacity = value;
    requestAnimationFrame((t) => animate(t));
  } else element.style.opacity = 1;
}

В этом примере используется document.timeline.currentTime для установки нулевого значения перед первым вызовом requestAnimationFrame. document.timeline.currentTime соответствует аргументу timestamp, поэтому нулевое значение эквивалентно значению timestamp нулевого кадра.

const zero = document.timeline.currentTime;
requestAnimationFrame(animate);
function animate(timestamp) {
  const value = (timestamp - zero) / duration; // animation-timing-function: linear
  if (value < 1) {
    element.style.opacity = value;
    requestAnimationFrame((t) => animate(t));
  } else element.style.opacity = 1;
}

В этом примере анимация выполняется с помощью performance.now() вместо значения timestamp обратного вызова. Вы можете использовать это для достижения немного большей точности синхронизации, хотя дополнительная точность является переменной и не значительно увеличивается. Примечание: этот пример не позволяет надёжно синхронизировать вызовы обратного вызова анимации.

const zero = performance.now();
requestAnimationFrame(animate);
function animate() {
  const value = (performance.now() - zero) / duration;
  if (value < 1) {
    element.style.opacity = value;
    requestAnimationFrame((t) => animate(t));
  } else element.style.opacity = 1;
}

Спецификации

Спецификация
HTML
# dom-animationframeprovider-requestanimationframe

Совместимость с браузерами

Рабочие столы Мобильные устройства
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on IOS Samsung Internet WebView Android
requestAnimationFrame 2410
12До версии 17 Edge ненадёжно вызывает requestAnimationFrame перед циклом рисования.
23Параметр обратного вызова — DOMHighResTimestamp. Это означает точность в десятые доли микросекунды и ноль времени как performance.now().
11–42Параметр обратного вызова — DOMTimestamp. Это означает точность в миллисекунды и ноль времени как Date.now().
4–11Может вызываться без входных параметров.
1515 76 2518 2314–42 1414 76 1.51.0 4.4≤37

См. также

  • Window.cancelAnimationFrame()
  • DedicatedWorkerGlobalScope.requestAnimationFrame()
  • Анимация с помощью JavaScript: от setInterval к requestAnimationFrame - Статья блога
  • TestUFO: Проверьте свой веб-браузер на отклонения во времени requestAnimationFrame()
  • Firefox переходит к uint32_t для идентификатора запроса requestAnimationFrame

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API