Событие loopComplete

Событие loopComplete в Lottie Web относится к системе событий проигрывания анимации и срабатывает каждый раз после завершения одного полного цикла повторяющейся анимации. Оно является частью событийного API экземпляра анимации (AnimationItem) и используется в сценариях, где необходимо отслеживать именно факт завершения очередного повторения, а не финальное завершение всей анимации.

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

Ключевое отличие от события complete заключается в том, что complete срабатывает только один раз — в момент завершения всей анимации, если цикл ограничен, либо при окончании последнего прохода. В то время как loopComplete вызывается после каждого цикла, независимо от общего количества повторений.

Условия срабатывания

Событие активируется в следующих случаях:

  • включено зацикливание (loop: true);
  • задано числовое количество повторов (loop: n);
  • используется сегментированное воспроизведение с повторяющимися сегментами;
  • анимация достигает конечного кадра и автоматически возвращается к начальному.

При этом важно учитывать, что событие не зависит от способа управления проигрыванием — оно срабатывает как при автоматическом воспроизведении (autoplay), так и при программном управлении методом play().

Подписка на событие

В Lottie Web события привязываются к экземпляру анимации через метод addEventListener. Подписка на loopComplete выглядит следующим образом:

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

animation.addEventListener('loopComplete', () => {
  console.log('Цикл анимации завершён');
});

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

Структура передаваемых данных

Обработчик события получает объект события, содержащий контекст текущего состояния анимации. Обычно доступна информация о типе события и ссылке на экземпляр анимации:

animation.addEventListener('loopComplete', (event) => {
  console.log(event.type); // loopComplete
  console.log(event.target); // AnimationItem
});

Через event.target можно получить доступ ко всем методам и свойствам текущей анимации, включая управление воспроизведением, скоростью и текущими кадрами.

Взаимодействие с параметром loop

Поведение события напрямую зависит от конфигурации параметра loop.

Булевое значение:

loop: true

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

Числовое значение:

loop: 3

Анимация выполняет три полных цикла. Событие будет вызвано три раза, после чего воспроизведение завершится.

Отключённый цикл:

loop: false

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

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

При использовании сегментов (segments) анимация делится на логические диапазоны кадров. Каждый проход по сегменту рассматривается как отдельный цикл, и при возврате к началу сегмента также инициируется loopComplete.

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

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

Отличие от других событий

Событийная модель Lottie Web включает несколько ключевых триггеров:

  • enterFrame — вызывается на каждом кадре;
  • complete — завершение всей анимации;
  • loopComplete — завершение одного цикла;
  • pause и play — изменение состояния воспроизведения.

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

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

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

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

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

Поведение при изменении скорости воспроизведения

При изменении speed событие loopComplete продолжает срабатывать в конце цикла независимо от длительности его выполнения. Увеличение скорости сокращает интервал между вызовами, но не влияет на саму семантику события.

animation.setSpeed(2);

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

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

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

function onLoop(event) {
  console.log('цикл завершён');
}

animation.addEventListener('loopComplete', onLoop);

// удаление
animation.removeEventListener('loopComplete', onLoop);

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

Взаимодействие с остановкой и паузой

При вызове методов управления воспроизведением поведение события изменяется следующим образом:

  • pause() останавливает анимацию до достижения конца цикла — событие не срабатывает;
  • stop() сбрасывает прогресс на начальный кадр — текущий цикл не завершается;
  • goToAndStop() прерывает поток и исключает генерацию loopComplete.

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

Поведение в SVG, Canvas и HTML renderer

Рендерер не влияет на семантику события. Независимо от того, используется ли SVG, Canvas или HTML, loopComplete вызывается на уровне логики Lottie, а не графического слоя. Это обеспечивает идентичное поведение анимаций в разных средах исполнения.

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

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

  • последовательная загрузка данных после каждого цикла;
  • переключение состояний UI;
  • управление несколькими анимациями в цепочке;
  • реализация тайминговых сценариев без использования setInterval.

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

Особенности накопления вызовов

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

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