Синхронизация с requestAnimationFrame

Для создания плавной анимации в Two.js используется requestAnimationFrame (rAF) — встроенный в браузеры метод, оптимизированный для перерисовки графики с частотой обновления экрана. Он автоматически синхронизирует кадры с частотой обновления монитора, снижает нагрузку на процессор и предотвращает “дребезг” анимации.

В Two.js метод Two.update() отвечает за обновление сцен и объектов. Обычно он вызывается внутри функции обратного вызова rAF для обеспечения непрерывной анимации. Стандартный подход выглядит так:

const two = new Two({
  width: 800,
  height: 600
}).appendTo(document.body);

const circle = two.makeCircle(400, 300, 50);
circle.fill = '#FF8000';
circle.stroke = '#000';
circle.linewidth = 5;

function animate(time) {
  // Изменение свойств объектов для анимации
  circle.rotation += 0.02;
  
  // Обновление сцены
  two.update();

  // Следующий кадр
  requestAnimationFrame(animate);
}

// Старт анимации
requestAnimationFrame(animate);

Ключевые моменты синхронизации

  1. Использование одного глобального цикла Для сложных сцен с несколькими объектами рекомендуется запускать один rAF-цикл, который обновляет все объекты и вызывает two.update(). Это предотвращает рассинхронизацию кадров и чрезмерную нагрузку на браузер.

  2. Передача временного параметра Функция обратного вызова rAF получает время в миллисекундах, которое можно использовать для расчёта анимации с учётом прошедшего времени:

let lastTime = 0;

function animate(time) {
  const delta = time - lastTime;
  lastTime = time;

  circle.rotation += 0.001 * delta;

  two.update();
  requestAnimationFrame(animate);
}

requestAnimationFrame(animate);

Использование delta делает анимацию независимой от частоты кадров, что важно для плавного движения на разных устройствах.

  1. Объединение анимаций с Two.js Tween Two.js поддерживает интеграцию с tween-библиотеками. Для согласованной анимации необходимо запускать обновление tween внутри rAF-цикла, перед вызовом two.update():
function animate(time) {
  TWEEN.update(time); // обновление tween
  two.update();
  requestAnimationFrame(animate);
}

requestAnimationFrame(animate);

Оптимизация производительности

  • Отключение ненужных обновлений: если сцена статична, не вызывать two.update() каждый кадр. Можно запускать анимацию только при изменении объектов.
  • Использование two.pause() и two.play() при временной остановке анимации вместо удаления rAF-цикла.
  • Сглаживание движения: применять интерполяцию свойств объектов через delta времени, чтобы движение было линейным независимо от FPS.

Обновление нескольких сцен

В проектах с несколькими экземплярами Two.js каждая сцена может иметь свой rAF, но эффективнее синхронизировать их в одном цикле:

const two1 = new Two({ width: 400, height: 300 }).appendTo('#canvas1');
const two2 = new Two({ width: 400, height: 300 }).appendTo('#canvas2');

function animate(time) {
  two1.update();
  two2.update();
  requestAnimationFrame(animate);
}

requestAnimationFrame(animate);

Это снижает накладные расходы на браузер и упрощает управление анимацией.

Взаимодействие с DOM и событиями

  • Анимация в rAF может быть поставлена на паузу при скрытии вкладки браузера, что экономит ресурсы.
  • Для реактивного управления объектами Two.js через события DOM можно обновлять их состояние внутри rAF-цикла. Это обеспечивает плавную интеграцию с пользовательским вводом.

Заключение по синхронизации

Использование requestAnimationFrame вместе с two.update() — стандартный и эффективный метод анимации в Two.js. Важные аспекты: использование единого цикла для всех объектов, применение дельты времени для независимой от FPS анимации и оптимизация обновлений для повышения производительности.