Циклические анимации

Базовый принцип повторного запуска анимации

Библиотека Vivus не содержит отдельного параметра «loop» в классическом смысле бесконечной анимации, однако цикличность реализуется через управление жизненным циклом экземпляра SVG-анимации. Основной механизм повторения строится на методах управления состоянием:

  • play() — запуск анимации
  • reset() — сброс к начальному состоянию
  • stop() — остановка воспроизведения

Циклическая анимация формируется комбинацией onReady и onComplete, где завершение анимации становится триггером нового запуска.

const animation = new Vivus('svg-element', {
  duration: 120,
  type: 'oneByOne'
}, function (obj) {
  obj.play();
});

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


Бесконечный цикл через onComplete

Основной способ организации циклической анимации — использование колбэка завершения.

const animation = new Vivus('svg-element', {
  duration: 100,
  type: 'delayed'
}, function (obj) {
  obj.play();
});

animation.onCompl ete = function () {
  animation.reset().play();
};

Механика основана на следующем процессе:

  1. SVG-линии отрисовываются до конца
  2. Срабатывает onComplete
  3. Выполняется reset(), возвращающий начальное состояние
  4. Снова вызывается play()

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


Контроль задержки между циклами

Чистое повторение анимации часто требует паузы между циклами. Для этого используется setTimeout, который вводит задержку между reset() и новым запуском.

animation.onCompl ete = function () {
  setTimeout(function () {
    animation.reset().play();
  }, 800);
};

Регулирование задержки позволяет:

  • синхронизировать анимации нескольких SVG
  • уменьшить визуальную монотонность
  • создать ритмические эффекты интерфейса

Управление количеством циклов

Базовая реализация Vivus не ограничивает количество повторов напрямую, поэтому счётчик циклов реализуется вручную.

let count = 0;
const maxLoops = 5;

const animation = new Vivus('svg-element', {
  duration: 80,
  type: 'sync'
});

animation.onCompl ete = function () {
  count++;

  if (count < maxLoops) {
    animation.reset().play();
  }
};

Подход позволяет:

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

Реверсивные циклы (эффект «туда-обратно»)

Плавный возврат к исходному состоянию создаётся через чередование play() и reset() с изменением направления логики воспроизведения.

Vivus не предоставляет встроенного reverse-режима, поэтому инверсия реализуется вручную:

let direction = 1;

const animation = new Vivus('svg-element', {
  duration: 120,
  type: 'delayed'
});

animation.onCompl ete = function () {
  if (direction === 1) {
    animation.reset().play();
    direction = 0;
  } else {
    animation.reset().play();
    direction = 1;
  }
};

Более стабильная версия реверсивного эффекта достигается через пересоздание экземпляра с разными параметрами отрисовки, например изменением порядка путей SVG.


Циклы с накоплением состояния

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

let speed = 80;

const animation = new Vivus('svg-element', {
  duration: speed,
  type: 'oneByOne'
});

animation.onCompl ete = function () {
  speed = Math.max(20, speed - 5);

  setTimeout(function () {
    animation.duration = speed;
    animation.reset().play();
  }, 300);
};

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


Синхронизация нескольких циклических анимаций

При работе с несколькими SVG-объектами циклы часто выравниваются по общему таймеру или событию завершения последней анимации.

const a1 = new Vivus('svg1', { duration: 100 });
const a2 = new Vivus('svg2', { duration: 140 });

let completed = 0;

function checkLoop() {
  completed++;

  if (completed === 2) {
    completed = 0;
    a1.reset().play();
    a2.reset().play();
  }
}

a1.onCompl ete = checkLoop;
a2.onCompl ete = checkLoop;

Подобная схема используется для:

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

Циклическая анимация с изменением параметров

Каждый новый цикл может сопровождаться изменением характеристик отрисовки:

  • duration
  • type
  • порядок линий SVG
  • цветовая логика (через внешние CSS-изменения)
const animation = new Vivus('svg-element', {
  duration: 90,
  type: 'sync'
});

let mode = 0;

animation.onCompl ete = function () {
  mode = (mode + 1) % 3;

  if (mode === 0) animation.type = 'delayed';
  if (mode === 1) animation.type = 'sync';
  if (mode === 2) animation.type = 'oneByOne';

  animation.reset().play();
};

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


Прерывание и перезапуск циклов

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

let running = true;

animation.onCompl ete = function () {
  if (!running) return;

  animation.reset().play();
};

// внешнее управление
running = false;
animation.stop();

Этот механизм используется в ситуациях:

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

Циклы с плавным стартом и завершением

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

animation.onCompl ete = function () {
  setTimeout(function () {
    animation.reset();

    requestAnimationFrame(function () {
      animation.play();
    });
  }, 500);
};

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