Перемотка и паузы

В системах анимации Popmotion ключевым элементом становится контроль времени исполнения. Любая анимация рассматривается как функция, зависящая от прогресса, где время перестаёт быть линейным и становится управляемым параметром.

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

Основная идея заключается в разделении:

  • источника времени (таймер, requestAnimationFrame)
  • внутреннего состояния анимации
  • управляющего интерфейса

Такое разделение позволяет манипулировать состоянием без пересоздания анимации.


Состояние выполнения и управляющий контроллер

После запуска анимации создаётся контроллер, инкапсулирующий текущее состояние:

  • текущее время
  • прогресс (0–1 или абсолютное значение)
  • состояние выполнения (active / paused / stopped)
  • параметры скорости

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

Типичный набор операций:

  • pause() — замораживание текущего состояния
  • play() — продолжение с сохранённого момента
  • stop() — полная остановка и сброс
  • seek(value) — установка позиции времени
  • reverse() — инверсия направления воспроизведения
  • update() — внутреннее обновление состояния

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


Приостановка и возобновление

Механизм паузы реализуется через фиксацию временной метки, с которой была остановлена анимация.

При вызове приостановки фиксируются:

  • прошедшее время с начала анимации
  • текущая позиция интерполяции
  • скорость воспроизведения

Далее цикл обновления продолжает выполняться, но вычисление прогресса блокируется.

import { tween } from 'popmotion';

const animation = tween({
  from: 0,
  to: 100,
  duration: 2000
}).start({
  update: v => console.log(v)
});

setTimeout(() => {
  animation.pause();
}, 500);

setTimeout(() => {
  animation.play();
}, 1500);

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


Перемотка как произвольный доступ к времени

Перемотка реализует концепцию «random access timeline». Вместо линейного воспроизведения появляется возможность установки любого положения внутри диапазона анимации.

Метод перемотки принимает:

  • абсолютное значение времени
  • или нормализованный прогресс

При изменении позиции вычисление интерполяции пересчитывается немедленно.

const controls = tween({
  from: 0,
  to: 1000,
  duration: 4000
}).start({
  update: v => console.log(v)
});

setTimeout(() => {
  controls.seek(2000);
}, 1000);

Внутри механизма происходит преобразование:

  • время → прогресс
  • прогресс → значение интерполяции

При этом все easing-функции применяются повторно, как если бы анимация «всегда находилась» в этой точке.


Обратное воспроизведение

Режим реверса строится на инверсии временной оси. Вместо увеличения прогресса от 0 до 1 используется движение от 1 к 0.

Внутренне это реализуется через коэффициент скорости:

  • положительное значение — прямое направление
  • отрицательное значение — обратное
const animation = tween({
  from: 0,
  to: 500,
  duration: 3000
}).start();

setTimeout(() => {
  animation.reverse();
}, 1500);

При изменении направления сохраняется текущая позиция, а пересчёт времени происходит относительно неё.

Важно, что реверс не требует пересоздания анимации — меняется только интерпретация времени.


Управление скоростью и эффект перемотки

Скорость анимации является множителем временной шкалы. Она влияет на то, как быстро происходит переход между состояниями.

  • 1 — нормальная скорость
  • 0.5 — замедление
  • 2 — ускорение
  • -1 — обратное воспроизведение

Изменение скорости эквивалентно масштабированию времени, а не пересчёту значений.

const controls = tween({
  from: 0,
  to: 300,
  duration: 3000
}).start();

setTimeout(() => {
  controls.speed = -1;
}, 1000);

Такой подход позволяет комбинировать ускорение и перемотку без дополнительных вычислений интерполяции.


Таймлайн и глобальная синхронизация

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

Каждая анимация:

  • получает глобальное время
  • вычисляет локальное смещение
  • синхронизируется с общим прогрессом

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

import { timeline } from 'popmotion';

const sequence = timeline([
  tween({ from: 0, to: 100, duration: 1000 }),
  tween({ from: 100, to: 200, duration: 1000 })
]).start();

setTimeout(() => {
  sequence.seek(500);
}, 800);

Перемещение по таймлайну автоматически пересчитывает состояние каждого шага.


Пауза в составе сложных цепочек

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

При этом сохраняется локальное состояние каждого сегмента:

  • позиция внутри шага
  • текущий easing
  • накопленное время

После возобновления все элементы продолжают выполнение синхронно, без десинхронизации.


Перемотка внутри физически-инерционных анимаций

В системах с физикой (spring, inertia) перемотка работает иначе, чем в tween-анимациях. Вместо прямого задания времени происходит восстановление состояния системы:

  • позиция
  • скорость
  • ускорение

При seek() происходит пересчёт состояния системы на основе модели движения.

Это означает, что перемотка не просто устанавливает значение, а пересчитывает динамику системы с заданной точки времени.


Интеграция пауз и перемотки в единый цикл

Все операции управления временем объединяются в один цикл обновления:

  • проверка состояния (paused / playing)
  • вычисление delta-time
  • применение скорости
  • обновление прогресса
  • интерполяция значения
  • вызов update callback

Пауза отключает шаг delta-time, перемотка переопределяет базовое значение времени, а скорость масштабирует его.

Так формируется единая модель управления временем, в которой отсутствует разделение между «воспроизведением» и «изменением состояния» — есть только трансформация временной координаты.