Повторяемость анимации в mo.js строится вокруг управления объектами
Timeline, Tween, Shape,
Burst и их состояниями выполнения. Любая сложная
последовательность фактически представляет собой граф зависимостей
времени, где каждый элемент может быть перезапущен, перемотан или
синхронизирован с другими.
Ключевая особенность системы — отделение описания анимации от её исполнения. Это позволяет многократно запускать одну и ту же композицию без пересоздания объектов.
Любой анимационный объект поддерживает методы управления состоянием:
play() — запуск с текущей позицииpause() — остановкаstop() — сброс в началоreplay() — остановка и запуск с началаНа уровне отдельного tween:
const tween = new mojs.Tween({
duration: 1000,
onUpdate: (p) => {
console.log(p);
}
});
tween.play();
tween.replay();
Метод replay() эквивалентен последовательности
stop() → play(), но выполняется атомарно, без
промежуточных кадровых состояний.
Timeline объединяет несколько анимаций в единый
управляющий объект. Повтор всей последовательности выполняется через
управление самим таймлайном.
const circle = new mojs.Shape({
shape: 'circle',
radius: { 0: 50 },
duration: 800
});
const square = new mojs.Shape({
shape: 'rect',
radius: { 0: 40 },
duration: 800,
delay: 200
});
const timeline = new mojs.Timeline({
repeat: 0
});
timeline.add(circle, square);
timeline.play();
timeline.replay();
При вызове replay() происходит:
0Для корректного повторного запуска важно учитывать внутренние состояния tween:
progress)t)delay)isFinished)Принудительный сброс реализуется через
setProgress(0):
timeline.setProgress(0);
timeline.play();
Такой подход используется при сложных композициях, где
replay() недостаточно из-за внешних зависимостей
состояния.
Встроенный механизм циклического воспроизведения задаётся параметром
repeat.
const tween = new mojs.Tween({
duration: 600,
repeat: 3
});
Поведение:
repeat: 0 — однократное выполнениеrepeat: 3 — три дополнительных повтора после первого
запускаrepeat: -1 — бесконечный циклПри каждом цикле выполняется полный пересчёт прогресса от
0 до 1.
Для точного управления повтором используются события жизненного цикла:
onStartonUpdateonCompleteonRepeatconst tween = new mojs.Tween({
duration: 1000,
repeat: 2,
onRepeat: () => {
console.log('цикл завершён, начинается повтор');
}
});
Событие onRepeat вызывается перед каждым новым циклом,
кроме первого запуска.
Групповые конструкции mojs требуют синхронизации всех
дочерних элементов.
const burst = new mojs.Burst({
radius: { 0: 100 },
count: 5
});
const timeline = new mojs.Timeline();
timeline.add(burst);
function restart() {
timeline.stop();
timeline.setProgress(0);
timeline.play();
}
Такой подход гарантирует полное восстановление исходного состояния всех вложенных объектов.
Низкоуровневый контроль возможен через прямую установку временной позиции:
timeline.tune({}).setProgress(0.5);
timeline.play();
При повторе анимации иногда используется сохранение контрольных точек:
0)0.5)1)Это позволяет реализовать частичные повторы сегментов последовательности.
replay() и repeat решают разные задачи:
replay() — ручной перезапускrepeat — автоматический циклПример комбинированного использования:
const tween = new mojs.Tween({
duration: 800,
repeat: 2
});
tween.play();
// внешний перезапуск всей серии
setTimeout(() => {
tween.replay();
}, 5000);
В этом случае цикл повторяется внутри и дополнительно может быть перезапущен извне.
При работе с несколькими уровнями вложенности (Timeline → Timeline → Tween) возникает необходимость каскадного сброса.
Алгоритм восстановления:
function fullReset(timeline) {
timeline.stop();
timeline.setProgress(0);
timeline.children.forEach(child => {
child.stop && child.stop();
child.setProgress && child.setProgress(0);
});
timeline.play();
}
Burst генерирует набор независимых tween-элементов. При
повторном запуске важно учитывать:
const burst = new mojs.Burst({
count: 8,
radius: { 0: 120 },
children: {
shape: 'circle',
radius: { 10: 0 }
}
});
function replayBurst() {
burst.replay();
}
Каждый повтор приводит к новой генерации внутренних объектов, а не к их реанимации.
При параллельных композициях применяется единый управляющий слой:
const t1 = new mojs.Timeline();
const t2 = new mojs.Timeline();
const master = new mojs.Timeline();
master.add(t1, t2);
function restartAll() {
master.stop();
master.setProgress(0);
master.play();
}
Синхронный reset обеспечивает отсутствие рассинхронизации фаз между анимациями.
Для динамических последовательностей используется модификация
состояния в onRepeat:
let radius = 50;
const shape = new mojs.Shape({
shape: 'circle',
radius: radius,
duration: 600,
repeat: 5,
onRepeat: () => {
radius += 10;
shape.tune({ radius });
}
});
Каждый цикл изменяет конфигурацию без пересоздания объекта.
При длительных циклах важны:
Стабильная схема повторения строится на комбинации:
stop()setProgress(0)play()что обеспечивает детерминированное состояние системы на каждом запуске.