Получение состояния анимации

Motion One возвращает при запуске анимации не просто побочный эффект изменения стилей, а полноценный объект управления, через который можно наблюдать текущее состояние анимации, синхронизироваться с её жизненным циклом и управлять воспроизведением после старта.

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

import { animate } from "motion";

const animation = animate(
  ".box",
  { x: 300, opacity: 0 },
  { duration: 2 }
);

Возвращаемый объект сохраняет связь с активным таймлайном и предоставляет доступ к ключевым параметрам:

  • текущее время воспроизведения
  • состояние проигрывания
  • промисы завершения
  • методы управления (pause, play, stop, cancel)
  • события жизненного цикла

Состояние воспроизведения playState

Основной индикатор текущего состояния анимации — playState. Он отражает фазу, в которой находится анимация в конкретный момент времени.

Типичные значения:

  • idle — анимация создана, но не запущена
  • running — активное воспроизведение
  • paused — остановка с сохранением прогресса
  • finished — завершённое выполнение всех ключевых кадров
console.log(animation.playState);

Изменение playState происходит синхронно с внутренним таймером, что позволяет использовать его как источник истины для UI-индикаторов, прогресс-баров и систем синхронизации.

Отслеживание завершения через finished

Каждая анимация содержит Promise finished, который резолвится после достижения финального кадра.

animation.finished.then(() => {
  console.log("Анимация завершена");
});

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

Особенности поведения:

  • Promise создаётся один раз на жизненный цикл анимации
  • при повторном запуске создаётся новый экземпляр Promise
  • отмена анимации приводит к его отклонению или завершению в зависимости от состояния

Управление текущим временем

Свойство currentTime отражает текущее положение воспроизведения в миллисекундах.

console.log(animation.currentTime);

При паузе значение фиксируется, при воспроизведении увеличивается линейно (или нелинейно при использовании easing и keyframes).

Изменение currentTime вручную позволяет реализовать:

  • скраббинг (перемотку)
  • синхронизацию с внешними таймлайнами
  • интерактивные анимации, управляемые скроллом
animation.currentTime = 500;

События жизненного цикла

Анимация предоставляет набор callback-хуков, позволяющих реагировать на изменения состояния без polling-подхода.

onfinish

Срабатывает при достижении конца анимации.

const animation = animate(".box", { x: 200 }, {
  duration: 1,
  onFinish: () => {
    console.log("finish");
  }
});

onupdate

Вызывается на каждом кадре обновления состояния.

animate(".box", { x: 300 }, {
  duration: 2,
  onUpdate: (latest) => {
    console.log(latest.x);
  }
});

Параметр latest содержит вычисленные значения свойств на текущем кадре, что позволяет отслеживать промежуточное состояние без обращения к DOM.

Методы управления состоянием

Объект анимации содержит методы прямого контроля над жизненным циклом.

pause

Фиксирует текущее состояние без сброса прогресса.

animation.pause();

Состояние переходит в paused, currentTime сохраняется.

play

Возобновляет выполнение с текущей позиции.

animation.play();

При повторном запуске после завершения создаётся новая итерация анимации.

cancel

Полностью прекращает выполнение и сбрасывает внутреннее состояние.

animation.cancel();

После вызова:

  • playState становится idle
  • стили возвращаются к исходным значениям (в зависимости от конфигурации)
  • промисы завершаются

Синхронизация нескольких анимаций через состояние

Контроль состояния позволяет связывать несколько анимаций в единую систему координат.

const a = animate(".a", { x: 100 }, { duration: 1 });
const b = animate(".b", { x: 200 }, { duration: 1 });

a.finished.then(() => b.play());

Подобный подход используется для построения последовательных сцен и составных интерфейсных переходов.

Интроспекция активных параметров

Состояние анимации включает доступ к текущим вычисленным параметрам:

  • progress (0–1)
  • velocity (скорость изменения)
  • time scaling (если применяется playbackRate)
  • easing-результат текущего кадра
animate(".box", { x: 400 }, {
  duration: 3,
  onUpdate: (_, info) => {
    console.log(info.time, info.progress);
  }
});

Управление скоростью и влияние на состояние

Изменение playbackRate влияет на интерпретацию времени и состояние выполнения.

animation.playbackRate = 2;

Особенности:

  • значения > 1 ускоряют анимацию
  • значения между 0 и 1 замедляют
  • отрицательные значения разворачивают прогресс

Состояние playState при этом остаётся running, но временная шкала изменяется.

Повторные запуски и жизненный цикл состояния

После завершения анимации её состояние не обнуляется автоматически. Повторный вызов play() приводит к созданию нового цикла воспроизведения, при этом:

  • finished создаётся заново
  • currentTime возвращается к нулю (или начальному значению)
  • playState снова становится running
animation.finished.then(() => {
  animation.play();
});

Синхронное и асинхронное наблюдение состояния

Состояние может отслеживаться двумя подходами:

  • синхронно через playState и currentTime
  • асинхронно через finished, onUpdate, onFinish

Синхронный подход используется для UI-индикаторов, асинхронный — для логики переходов и цепочек анимаций.

Заморозка и восстановление состояния

При необходимости сохранения состояния между сессиями можно фиксировать ключевые параметры:

  • currentTime
  • playState
  • вычисленные значения ключевых свойств

Дальнейшее восстановление осуществляется через установку времени и повторный запуск:

animation.pause();
const saved = animation.currentTime;

animation.currentTime = saved;
animation.play();

Такой механизм используется в сложных интерфейсах с сохранением прогресса и интерактивными таймлайнами.