Переключение состояний анимации

Базовая модель состояния анимации

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

Ключевые состояния:

  • текущее время (progress / current frame)
  • направление воспроизведения (forward / reverse)
  • скорость (speed)
  • режим цикла (loop / once)
  • состояние активности (playing / paused / stopped)

Экземпляр анимации создаётся через lottie.loadAnimation, после чего управление состоянием осуществляется через API объекта анимации.

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

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


Запуск и остановка воспроизведения

Запуск анимации

Метод play() переводит анимацию в состояние активного воспроизведения с текущего кадра.

anim.play();

Если перед этим анимация была остановлена на конкретном кадре, воспроизведение продолжится с этой точки.

Пауза

Метод pause() фиксирует текущее состояние без сброса времени.

anim.pause();

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

Полная остановка

Метод stop() переводит анимацию в начальный кадр и прекращает воспроизведение.

anim.stop();

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


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

Lottie Web поддерживает изменение направления анимации во время выполнения.

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

anim.setDirection(1);  // вперёд
anim.setDirection(-1); // назад

Изменение направления не сбрасывает текущее положение, что позволяет создавать эффекты «обратного воспроизведения» интерфейсных переходов.

Комбинация с play() позволяет мгновенно переключать динамику:

anim.setDirection(-1);
anim.play();

Контроль скорости анимации

Скорость задаётся коэффициентом относительно оригинальной частоты кадров.

anim.setSpeed(2); // ускорение в 2 раза
anim.setSpeed(0.5); // замедление

Изменение скорости влияет на все последующие кадры, не сбрасывая текущее состояние.

Типичные сценарии:

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

Переключение между сегментами анимации

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

Запуск сегмента

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

Второй параметр true означает принудительное воспроизведение указанного диапазона.

Сегменты часто используются для:

  • состояний кнопок (idle → hover → active)
  • пошаговых сценариев интерфейса
  • анимаций загрузки

Последовательное управление сегментами

anim.playSegments([0, 15], true);
anim.addEventListener('complete', () => {
  anim.playSegments([15, 30], true);
});

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


Переход к конкретному кадру

Прямой переход без воспроизведения

anim.goToAndStop(45, true);

Используется для фиксации состояния интерфейса на конкретном кадре.

Переход с воспроизведением

anim.goToAndPlay(10, true);

Позволяет инициировать анимацию с заданной точки.

Второй аргумент определяет, используется ли значение как кадр (true) или как прогресс (false).


Работа с прогрессом анимации

Прогресс представляет собой нормализованное значение от 0 до 1.

anim.goToAndStop(0.5, false);

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

Привязка к прокрутке

window.addEventListener('scroll', () => {
  const scrollTop = window.scrollY;
  const maxScroll = document.body.scrollHeight - window.innerHeight;

  const progress = scrollTop / maxScroll;
  anim.goToAndStop(progress, false);
});

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


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

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

Переход к маркеру

anim.play('start_state');

Имена маркеров позволяют строить семантические переходы:

  • loading
  • success
  • error
  • idle

Вместо числовых диапазонов используются логические состояния.


Системы переключения состояний

Простейшая модель состояний

const states = {
  idle: [0, 20],
  hover: [20, 40],
  active: [40, 60]
};

function setState(name) {
  anim.playSegments(states[name], true);
}

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


Реализация конечного автомата

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

const transitions = {
  idle: {
    hover: 'hover',
    click: 'active'
  },
  hover: {
    leave: 'idle',
    click: 'active'
  },
  active: {
    complete: 'idle'
  }
};

let currentState = 'idle';

function transition(event) {
  const next = transitions[currentState][event];
  if (!next) return;

  currentState = next;
  setState(next);
}

Каждое состояние связано с конкретным сегментом анимации.


Динамическая смена анимаций

В некоторых сценариях требуется полная замена JSON-анимации без пересоздания контейнера.

anim.destroy();

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

Такой подход используется при смене контекста интерфейса, когда логика состояния полностью изменяется.


Сохранение и восстановление состояния

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

const frame = anim.currentFrame;

anim.goToAndStop(frame, true);

Для восстановления после пересоздания:

const savedProgress = anim.currentFrame / anim.totalFrames;
anim.goToAndStop(savedProgress, false);

Событийная модель переключения состояний

Lottie Web предоставляет события для отслеживания изменений состояния.

anim.addEventListener('enterFrame', (e) => {
  // контроль текущего кадра
});

anim.addEventListener('complete', () => {
  // завершение сегмента
});

Основные события:

  • complete — завершение анимации или сегмента
  • loopComplete — завершение цикла
  • enterFrame — изменение кадра
  • data_ready — загрузка данных

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


Инверсия и обратные переходы

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

anim.setDirection(-1);
anim.play();

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

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

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


Управление множественными состояниями

При наличии нескольких анимаций или слоёв состояния синхронизируются через общий контроллер.

const animations = [anim1, anim2, anim3];

function setGlobalSpeed(speed) {
  animations.forEach(a => a.setSpeed(speed));
}

Для синхронного переключения состояния:

function playAll() {
  animations.forEach(a => a.play());
}

Переключение через внешние триггеры

Состояния часто управляются событиями DOM:

button.addEventListener('mouseenter', () => {
  anim.playSegments([10, 30], true);
});

button.addEventListener('mouseleave', () => {
  anim.playSegments([30, 10], true);
});

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


Детерминированное управление состояниями

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

function setAnimationState({ frame, speed, direction }) {
  anim.setSpeed(speed);
  anim.setDirection(direction);
  anim.goToAndStop(frame, true);
}

Это устраняет неопределённость при сложных переходах и облегчает отладку.


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

Анимация может отражать состояние приложения:

function updateStatus(status) {
  switch (status) {
    case 'loading':
      anim.playSegments([0, 20], true);
      break;
    case 'success':
      anim.playSegments([20, 40], true);
      break;
    case 'error':
      anim.playSegments([40, 60], true);
      break;
  }
}

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