Воспроизведение сегментов анимации

Понятие сегмента в Lottie-анимации

Анимация в формате Lottie представляет собой временную шкалу, состоящую из ключевых кадров, экспортированных из After Effects через Bodymovin. Внутри этой шкалы можно выделять сегменты — диапазоны кадров, которые интерпретируются как самостоятельные логические части анимации.

Сегмент определяется парой значений:

  • начальный кадр
  • конечный кадр

Такая структура позволяет воспроизводить не всю анимацию целиком, а её фрагменты, что критично для интерфейсных сценариев: микроинтеракции, состояния UI, переходы между экранами.


Базовый механизм playSegments

Основной API для работы с сегментами в Lottie Web — метод playSegments.

animation.playSegments([10, 60], true);

Первый аргумент задаёт диапазон кадров:

  • 10 — стартовый кадр
  • 60 — конечный кадр

Второй аргумент управляет поведением переключения:

  • true — немедленный переход к сегменту с принудительным прерыванием текущего состояния
  • false — плавное продолжение очереди анимации

Внутренне механизм работает через переопределение текущего состояния таймлайна и установку ограничителей playback range.


Типы сегментов и способы их задания

Числовой диапазон кадров

Наиболее прямолинейный способ задания сегмента:

animation.playSegments([0, 30], true);

Используется абсолютная шкала кадров, соответствующая композиции After Effects.


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

Сегмент может задаваться в обратном порядке:

animation.playSegments([60, 10], true);

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


Множественные сегменты

Lottie поддерживает последовательность сегментов:

animation.playSegments([[0, 20], [20, 40], [40, 80]], true);

Поведение:

  • сегменты объединяются в очередь
  • воспроизведение происходит последовательно
  • каждый сегмент рассматривается как независимый playback-range

Управление очередью сегментов

При использовании playSegments с forceFlag = false сегменты добавляются в очередь:

animation.playSegments([10, 50], false);
animation.playSegments([50, 100], false);

В этом режиме движок:

  • не прерывает текущее воспроизведение
  • формирует внутренний список сегментов
  • переключает диапазон после завершения текущего блока

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


Связь сегментов и состояния анимации

Внутри Lottie Web существует несколько состояний воспроизведения:

  • play
  • pause
  • stop
  • segment playback mode

При вызове playSegments происходит переход в сегментный режим, при котором:

  • глобальный таймер композиции ограничивается диапазоном
  • нормализация времени выполняется относительно сегмента
  • currentFrame становится локальным внутри сегмента

Управление через goToAndPlay и goToAndStop

Хотя playSegments является основным механизмом, альтернативный контроль возможен через прямое позиционирование кадров.

animation.goToAndPlay(10, true);
animation.goToAndStop(50, true);

Параметр isFrame определяет интерпретацию значения:

  • true — значение трактуется как кадр
  • false — как время в секундах

Использование в связке с сегментами позволяет:

  • фиксировать точку входа
  • устанавливать контрольные состояния внутри сегмента
  • комбинировать с ручным playback

Использование маркеров как семантических сегментов

Помимо числовых диапазонов, сегменты могут быть определены через markers, экспортируемые из After Effects.

Маркер представляет собой именованную точку или диапазон на таймлайне.

animation.play("hover");

или через API маркеров:

const markers = animation.markers;

Структура маркера:

  • name
  • time
  • duration

Сегментное воспроизведение через маркеры фактически заменяет числовые диапазоны на семантические идентификаторы.


Преобразование маркеров в сегменты

Маркер может быть конвертирован в диапазон:

const marker = animation.markers.find(m => m.name === "open");

animation.playSegments(
  [marker.time, marker.time + marker.duration],
  true
);

Такой подход позволяет:

  • отделить логику от числовых значений
  • синхронизировать анимации с дизайнерскими именами
  • избежать хардкода кадров

Циклическое воспроизведение сегментов

Сегменты могут быть зациклены через комбинацию loop и playSegments:

animation.loop = true;
animation.playSegments([20, 40], true);

Поведение:

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

Дополнительно возможна ручная реализация через события:

animation.addEventListener("complete", () => {
  animation.playSegments([20, 40], true);
});

Сегменты и скорость воспроизведения

Скорость анимации влияет на сегмент аналогично полной композиции:

animation.setSpeed(2);
animation.playSegments([0, 50], true);

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

  • скорость применяется ко всему диапазону сегмента
  • временная шкала сегмента пересчитывается пропорционально
  • изменение скорости во время playback сохраняет позицию внутри сегмента

Инверсия направления внутри сегмента

Направление воспроизведения задаётся через setDirection:

animation.setDirection(-1);
animation.playSegments([0, 40], true);

Значения:

  • 1 — прямое воспроизведение
  • -1 — обратное воспроизведение

При обратном направлении:

  • стартовой точкой становится конечный кадр сегмента
  • конечной — начальный

Сегменты и событийная модель

Lottie Web предоставляет события для контроля завершения сегментов:

animation.addEventListener("complete", () => {
  // завершён текущий сегмент
});

Дополнительно используются:

  • enterFrame — каждый кадр
  • loopComplete — завершение цикла
  • segmentStart (в некоторых реализациях через кастомные обёртки)

Событийная модель позволяет строить state-machine поверх сегментов.


Прерывание и перезапуск сегмента

Поведение при повторном вызове playSegments зависит от forceFlag:

animation.playSegments([10, 40], true);
animation.playSegments([50, 90], true);

В этом случае:

  • текущий сегмент прерывается
  • начинается новый диапазон

При false:

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

Динамическое формирование сегментов

Сегменты могут формироваться на основе вычислений:

const start = 0;
const step = 25;

for (let i = 0; i < 4; i++) {
  animation.playSegments([start + i * step, start + (i + 1) * step], false);
}

Такой подход используется для:

  • разбиения длинных анимаций на шаги
  • управления прогрессом интерфейса
  • синхронизации с пользовательскими действиями

Сегменты и производительность

Использование сегментов влияет на производительность косвенно:

  • уменьшается область активного рендеринга
  • снижается нагрузка на интерполяцию ключевых кадров вне диапазона
  • оптимизируется работа requestAnimationFrame цикла

Однако сама композиция остаётся загруженной целиком, поэтому выигрыш проявляется преимущественно в логике управления временем, а не в памяти.


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

Сегментный подход позволяет представить анимацию как набор состояний:

  • 0–20 — инициализация
  • 20–40 — активное состояние
  • 40–60 — завершение
  • 60–80 — сброс

Каждое состояние становится независимым playback-блоком:

const states = {
  init: [0, 20],
  active: [20, 40],
  done: [40, 60],
  reset: [60, 80]
};

animation.playSegments(states.active, true);

Такой подход заменяет ручное управление keyframe timeline логикой управления UI.


Комбинирование сегментов с внешним контроллером

Сегменты часто связываются с внешними событиями интерфейса:

button.addEventListener("mousedown", () => {
  animation.playSegments([0, 30], true);
});

button.addEventListener("mouseup", () => {
  animation.playSegments([30, 60], true);
});

В этом случае Lottie функционирует как реактивный визуальный слой, управляемый внешней логикой.


Итоговая модель поведения сегментов

Сегментное воспроизведение в Lottie Web формирует абстракцию:

  • линейная временная шкала → дискретные состояния
  • глобальная анимация → локальные диапазоны кадров
  • continuous playback → управляемые блоки воспроизведения

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