Repeat - повторение анимации

Повторение (repeat) — один из ключевых инструментов управления жизненным циклом анимации в библиотеке mo.js. Он позволяет воспроизводить анимацию несколько раз без ручного перезапуска, обеспечивая компактный и выразительный код.


Базовое свойство repeat

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

const circle = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 50 },
  duration: 1000,
  repeat: 2
});

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

  • Значение repeat: 2 означает, что анимация выполнится 3 раза всего (1 начальный + 2 повтора)
  • По умолчанию repeat равен 0 (без повторений)

Свойство yoyo

Для создания эффекта возврата используется yoyo. При включении анимация будет проигрываться вперёд и назад.

const circle = new mojs.Shape({
  radius: { 0: 50 },
  duration: 1000,
  repeat: 2,
  yoyo: true
});

Поведение:

  • Первый цикл: от начального значения к конечному
  • Второй цикл: обратно к начальному
  • Повторы продолжают чередование направлений

Управление задержками между повторами

Для создания пауз между циклами используется repeatDelay.

const circle = new mojs.Shape({
  radius: { 0: 50 },
  duration: 1000,
  repeat: 3,
  repeatDelay: 500
});

Что происходит:

  • После каждого завершения анимации добавляется задержка 500 мс
  • Затем начинается следующий цикл

Комбинирование delay и repeatDelay

  • delay — задержка перед первым запуском
  • repeatDelay — задержка между повторами
const circle = new mojs.Shape({
  radius: { 0: 50 },
  duration: 1000,
  delay: 300,
  repeat: 2,
  repeatDelay: 400
});

Порядок выполнения:

  1. Задержка 300 мс
  2. Первый цикл
  3. Задержка 400 мс
  4. Второй цикл
  5. Задержка 400 мс
  6. Третий цикл

Бесконечное повторение

Для бесконечного воспроизведения используется значение Infinity.

const pulse = new mojs.Shape({
  radius: { 20: 40 },
  duration: 800,
  repeat: Infinity,
  yoyo: true
});

Применение:

  • Пульсации
  • Индикаторы загрузки
  • Фоновые эффекты

Синхронизация повторов в Timeline

При использовании mojs.Timeline повтор можно задавать как на уровне отдельных анимаций, так и для всей временной шкалы.

const shape1 = new mojs.Shape({
  radius: { 0: 30 },
  duration: 500
});

const shape2 = new mojs.Shape({
  radius: { 30: 0 },
  duration: 500
});

const timeline = new mojs.Timeline({
  repeat: 2
});

timeline.add(shape1, shape2);
timeline.play();

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

  • Повтор применяется ко всей последовательности
  • Все вложенные анимации воспроизводятся заново

Управление направлением повторов

При сочетании repeat и yoyo важно учитывать:

Свойство Эффект
repeat Количество повторений
yoyo: false Всегда одно направление
yoyo: true Чередование направлений

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

Значение repeat можно изменять программно:

const shape = new mojs.Shape({
  radius: { 0: 50 },
  duration: 1000
});

shape.play();
shape.repeat(3);

Также доступны методы управления:

  • play() — запуск
  • pause() — пауза
  • stop() — остановка

События и повторение

Для отслеживания повторов используются callbacks:

const shape = new mojs.Shape({
  radius: { 0: 50 },
  duration: 1000,
  repeat: 2,
  onRepeatStart() {
    console.log('Повтор начался');
  },
  onRepeatComplete() {
    console.log('Повтор завершён');
  }
});

Возможности:

  • Логирование
  • Синхронизация с другими анимациями
  • Запуск сторонних эффектов

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

1. Пульсация элемента

new mojs.Shape({
  shape: 'circle',
  scale: { 1: 1.5 },
  opacity: { 1: 0 },
  duration: 1000,
  repeat: Infinity
}).play();

2. Анимация «дыхания»

new mojs.Shape({
  scale: { 1: 1.2 },
  duration: 800,
  repeat: Infinity,
  yoyo: true
}).play();

3. Мигание

new mojs.Shape({
  opacity: { 1: 0 },
  duration: 200,
  repeat: 5,
  yoyo: true
}).play();

Оптимизация производительности

  • Избегать чрезмерного количества бесконечных анимаций
  • Использовать repeatDelay вместо сложной логики таймеров
  • Объединять анимации в Timeline для централизованного управления
  • Минимизировать количество DOM-элементов

Распространённые ошибки

1. Неправильное понимание количества повторов

repeat: 1 // это 2 проигрывания, а не 1

2. Конфликт yoyo и ожидаемого результата

При yoyo: true финальное состояние может отличаться от ожидаемого, так как анимация возвращается назад.


3. Отсутствие контроля бесконечных анимаций

repeat: Infinity

Без механизма остановки может привести к утечкам ресурсов.


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

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

new mojs.Shape({
  radius: { 0: 50 },
  duration: 1000,
  easing: 'ease.inout',
  repeat: 2
});

При yoyo easing применяется в обе стороны, что может визуально отличаться от линейного возврата.


Итеративные изменения параметров

В mo.js отсутствует встроенная поддержка изменения значений на каждом повторе, однако это можно реализовать через callbacks:

let count = 0;

const shape = new mojs.Shape({
  radius: { 0: 50 },
  duration: 500,
  repeat: 3,
  onRepeatStart() {
    count++;
    shape.tune({
      fill: count % 2 === 0 ? 'red' : 'blue'
    });
  }
});

Вложенные повторения

Повторения можно комбинировать:

const inner = new mojs.Shape({
  radius: { 0: 20 },
  duration: 300,
  repeat: 2
});

const timeline = new mojs.Timeline({
  repeat: 2
});

timeline.add(inner);

Результат:

  • Внутренняя анимация повторяется 3 раза
  • Вся последовательность — ещё 3 раза

Контроль состояния при повторении

Важно учитывать:

  • Начальные значения восстанавливаются при каждом цикле
  • Любые изменения вне tune() не сохраняются автоматически
  • Использование setProgress() позволяет вручную управлять состоянием

Связка с stagger-анимациями

При использовании mojs.stagger:

const shapes = new mojs.Stagger(mojs.Shape, {
  radius: { 0: 30 },
  duration: 500,
  repeat: 2
});

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


Глубокая настройка через Timeline

const tl = new mojs.Timeline({
  repeat: Infinity,
  repeatDelay: 1000
});

Позволяет:

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

Контроль завершения повторений

shape.then({
  scale: { 1: 0 },
  duration: 300
});

Метод then() запускается после всех повторов, что удобно для построения цепочек.


Управление через прогресс

shape.setProgress(0.5);

При повторении:

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

Архитектурные подходы

  • Использование repeat вместо ручных циклов setInterval
  • Централизация логики через Timeline
  • Разделение коротких и бесконечных анимаций
  • Минимизация состояния вне mo.js

Поведение при остановке

shape.stop();
  • Прерывает все повторы
  • Сбрасывает прогресс
  • Не вызывает onRepeatComplete

Итоговая схема работы repeat

  1. Выполняется delay

  2. Запускается первый цикл

  3. После завершения:

    • вызывается onRepeatStart
    • применяется repeatDelay
  4. Цикл повторяется заданное количество раз

  5. После последнего:

    • вызывается onComplete

Такое поведение делает repeat мощным инструментом для построения как простых, так и сложных анимационных сценариев.