onRepeatStart

Событие onRepeatStart используется для отслеживания момента, когда анимация в библиотеке mo.js начинает новый цикл повторения. Оно срабатывает каждый раз перед стартом очередной итерации, если для анимации задан параметр repeat.


Назначение и роль в жизненном цикле анимации

Внутренний цикл анимации в mo.js состоит из нескольких фаз:

  • инициализация (onStart)
  • выполнение (onUpdate)
  • завершение (onComplete)
  • повтор (repeat)

При наличии повторений (repeat > 0 или repeat: Infinity) между завершением одной итерации и началом следующей возникает точка, в которой срабатывает onRepeatStart.

Ключевая особенность:

  • onRepeatStart вызывается до начала следующего цикла, но после завершения предыдущего

Это позволяет:

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

Синтаксис использования

const tween = new mojs.Tween({
  duration: 1000,
  repeat: 3,
  onRepeatStart() {
    console.log('Новый цикл начался');
  }
});

tween.play();

Поведение при различных значениях repeat

Значение repeat Поведение onRepeatStart
0 Не вызывается
1 Не вызывается (нет повторов)
2+ Вызывается перед каждым новым циклом
Infinity Вызывается бесконечно

Порядок вызова событий

Для одной итерации с повторением порядок выглядит следующим образом:

  1. onStart

  2. onUpdate (многократно)

  3. onComplete

  4. onRepeatStartключевой момент

  5. следующий цикл:

    • onStart (не всегда вызывается повторно, зависит от типа анимации)
    • onUpdate

Практическое применение

1. Изменение параметров между итерациями

let scale = 1;

const tween = new mojs.Tween({
  duration: 500,
  repeat: 5,
  onRepeatStart() {
    scale += 0.2;
    console.log(`Новый масштаб: ${scale}`);
  }
});

2. Случайная модификация анимации

const circle = new mojs.Shape({
  shape: 'circle',
  fill: 'red',
  radius: 20,
  duration: 800,
  repeat: 3,
  onRepeatStart() {
    this.tune({
      fill: `hsl(${Math.random() * 360}, 100%, 50%)`
    });
  }
});

circle.play();

Метод tune() позволяет динамически менять свойства объекта перед новым циклом.


3. Синхронизация с другими анимациями

const timeline = new mojs.Timeline();

const tween1 = new mojs.Tween({
  duration: 1000,
  repeat: 2,
  onRepeatStart() {
    tween2.replay();
  }
});

const tween2 = new mojs.Tween({
  duration: 500
});

timeline.add(tween1, tween2).play();

Отличие от onStart и onComplete

Событие Когда вызывается
onStart При первом запуске
onComplete После завершения
onRepeatStart Перед новым циклом

Важно: onStart не всегда вызывается при каждом повторе — onRepeatStart специально предназначен для контроля именно повторных итераций.


Взаимодействие с задержками (delay)

Если задан delay:

const tween = new mojs.Tween({
  duration: 500,
  delay: 300,
  repeat: 2,
  onRepeatStart() {
    console.log('Повтор с задержкой');
  }
});

Поведение:

  • delay применяется к каждому циклу
  • onRepeatStart вызывается до применения задержки следующего цикла

Работа с yoyo

При использовании yoyo: true анимация чередует направление:

const tween = new mojs.Tween({
  duration: 600,
  repeat: 4,
  yoyo: true,
  onRepeatStart() {
    console.log('Смена направления');
  }
});

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

  • onRepeatStart вызывается перед каждым изменением направления
  • удобно для отслеживания “обратного” движения

Внутренние механизмы

onRepeatStart привязан к внутреннему счётчику повторений:

  • mo.js хранит текущий индекс итерации
  • после завершения цикла увеличивает счётчик
  • если достигнут предел — завершает
  • иначе вызывает onRepeatStart и запускает следующий цикл

Частые ошибки

1. Ожидание вызова при repeat: 1

repeat: 1 // повторов нет

Фактически:

  • 1 = одна итерация
  • повторов нет → onRepeatStart не вызывается

2. Путаница с onStart

onStart() {
  console.log('Каждый раз'); // ❌ неверно
}

onStart не гарантирует вызов на каждой итерации.


3. Изменение свойств без tune()

this.fill = 'blue'; // ❌ не работает

Правильно:

this.tune({ fill: 'blue' });

Комбинирование с Timeline

const timeline = new mojs.Timeline({
  repeat: 3,
  onRepeatStart() {
    console.log('Повтор всей последовательности');
  }
});

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

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

Отладка

onRepeatStart() {
  console.log('Iteration:', this._repeat);
}

Можно отслеживать:

  • номер текущего повтора
  • состояние анимации

Оптимизация

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

Типовые сценарии использования

  • генерация случайных эффектов (частицы, всплески)
  • управление состоянием UI
  • синхронизация нескольких таймлайнов
  • циклические анимации с изменяемыми параметрами
  • создание «живых» интерфейсов

Связанные параметры

  • repeat — определяет количество повторов
  • delay — задержка между циклами
  • yoyo — направление анимации
  • onUpdate — обновление кадра
  • onComplete — завершение

Краткая схема работы

[Цикл 1]
  ↓
onComplete
  ↓
onRepeatStart
  ↓
[Цикл 2]
  ↓
onComplete
  ↓
onRepeatStart
  ↓
...

Поведенческие особенности

  • не вызывается при первом запуске
  • вызывается строго перед новым циклом
  • работает одинаково для Tween, Shape и Timeline
  • сохраняет контекст (this) текущего объекта анимации

Расширенные паттерны

Динамическая эволюция анимации

let radius = 10;

const shape = new mojs.Shape({
  radius,
  repeat: 5,
  onRepeatStart() {
    radius += 5;
    this.tune({ radius });
  }
});

Генерация эффекта “затухания”

let opacity = 1;

const tween = new mojs.Tween({
  repeat: 4,
  onRepeatStart() {
    opacity -= 0.2;
    this.tune({ opacity });
  }
});

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

let duration = 1000;

const tween = new mojs.Tween({
  duration,
  repeat: 3,
  onRepeatStart() {
    duration -= 200;
    this.tune({ duration });
  }
});

Ограничения

  • не работает без repeat
  • не может отменить повтор — только реагирует на него
  • требует корректного использования this.tune()

Внутренний контекст this

Внутри onRepeatStart:

onRepeatStart() {
  console.log(this); // текущий Tween / Shape / Timeline
}

Доступны:

  • методы (play, pause, tune)
  • текущие параметры
  • состояние анимации

Использование в сложных системах

При построении сложных интерфейсов onRepeatStart часто используется как:

  • триггер обновления состояния
  • точка синхронизации
  • механизм генерации вариативности

Это делает его ключевым инструментом для создания динамических, неповторяющихся анимаций в mo.js.