Программная навигация по сегментам

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

Сегмент в контексте Lottie Web — это пара значений [startFrame, endFrame], задающая диапазон кадров внутри общей композиции. Работа с сегментами становится ключевым механизмом построения интерфейсных состояний, микроанимаций и управляемых переходов.


Модель кадров и временная шкала

В основе сегментной навигации лежит дискретная шкала кадров:

  • totalFrames — общее количество кадров анимации
  • frameRate — частота кадров, определяющая временную интерпретацию
  • currentFrame — текущая позиция воспроизведения

Каждый сегмент опирается на эти значения и работает в пределах общей временной оси.

const animation = lottie.loadAnimation({
  container: document.getElementById('anim'),
  renderer: 'svg',
  loop: false,
  autoplay: false,
  path: 'data.json'
});

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

Основной метод управления сегментами — playSegments. Он принимает массив диапазонов или один диапазон и флаг принудительного переключения.

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

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

  • старт воспроизведения происходит с 10 кадра
  • завершение — на 60 кадре
  • true принудительно сбрасывает текущую очередь анимации

При использовании нескольких сегментов возможно последовательное воспроизведение:

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

Каждый сегмент отрабатывает как независимый блок.


Логика сегментной композиции

Сегменты не существуют как отдельные сущности внутри JSON-файла Lottie. Они формируются на уровне runtime. Это означает:

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

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

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

Использование маркеров композиции

При экспорте из After Effects в JSON могут присутствовать маркеры (markers). Они позволяют задавать логические сегменты внутри композиции.

Типичная структура маркера:

"markers": [
  {
    "tm": 0,
    "dr": 30,
    "cm": "intro"
  },
  {
    "tm": 30,
    "dr": 60,
    "cm": "loop"
  }
]
  • tm — стартовый кадр
  • dr — длительность
  • cm — имя сегмента

Навигация по именованным сегментам

Хотя Lottie Web не предоставляет прямого API для работы с именами маркеров, они используются через внешнюю обработку:

const segments = {
  intro: [0, 30],
  loop: [30, 60],
  exit: [60, 90]
};

animation.playSegments(segments.loop, true);

Такая схема часто применяется в архитектуре состояний.


Управление направлением воспроизведения

Сегмент может воспроизводиться как вперёд, так и назад, если изменять направление через управление кадрами.

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

Обратный порядок кадров требует корректного задания диапазона.

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

  • start > end интерпретируется как обратное воспроизведение
  • направление влияет на интерполяцию ключевых кадров

Сегменты и зацикливание

Сегмент может быть зациклен через комбинацию loop и повторного вызова playSegments.

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

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

Альтернативный подход — ручной контроль:

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

Синхронизация сегментов с событиями

Сегментная навигация часто связывается с UI-событиями:

button.addEventListener('mouseenter', () => {
  animation.playSegments([0, 20], true);
});

button.addEventListener('mouseleave', () => {
  animation.playSegments([20, 40], true);
});

Каждое состояние UI соответствует отдельному диапазону кадров.


Прерывание текущего сегмента

Повторный вызов playSegments с true обрывает текущую анимацию:

animation.playSegments([0, 100], true);
animation.playSegments([100, 140], true);

Первый сегмент будет остановлен и заменён вторым.

Если требуется мягкое переключение, используется очередь событий:

animation.queue = [[0, 100], [100, 140]];

(реализация очереди создаётся на уровне приложения, так как встроенного механизма нет)


Работа с текущим кадром внутри сегмента

Контроль позиции внутри сегмента выполняется через currentFrame:

const frame = animation.currentFrame;

Для ограничения в пределах сегмента используется нормализация:

function clamp(frame, start, end) {
  return Math.max(start, Math.min(end, frame));
}

Переходы между сегментами

Плавные переходы требуют ручного интерполирования между диапазонами:

function transitionTo(next) {
  const current = animation.currentFrame;

  animation.playSegments(
    [current, next[1]],
    true
  );
}

Такая схема позволяет избежать резких скачков состояния.


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

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

animation.setSpeed(1.5);
animation.playSegments([10, 80], true);

При увеличении скорости:

  • сегмент сокращается по времени
  • логика ключевых кадров сохраняется

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

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

function buildSegment(progress, size) {
  return [progress, progress + size];
}

animation.playSegments(buildSegment(20, 40), true);

Это позволяет создавать адаптивные анимации, зависящие от состояния приложения.


Сегменты в сложных композициях

В больших анимациях сегментирование используется для:

  • разбиения UI на состояния (loading, success, error)
  • управления сценами
  • оптимизации рендеринга отдельных частей

Пример структуры:

const stateSegments = {
  loading: [0, 45],
  success: [45, 90],
  error: [90, 130]
};

Ограничения сегментной модели

При работе с сегментами необходимо учитывать:

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

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