В основе управления несколькими анимационными объектами в mo.js лежит
система временных связей между сущностями Tween,
Timeline, Shape и композициями анимаций.
Синхронизация достигается не через глобальный контроллер, а через
комбинацию задержек, относительных временных шкал и вложенных
таймлайнов.
Каждый объект анимации имеет собственный жизненный цикл, но при объединении в таймлайн они начинают подчиняться общей временной оси. Это позволяет выстраивать сложные сцены, где элементы появляются, трансформируются и исчезают согласованно, сохраняя при этом независимую логику каждого объекта.
Основным инструментом координации является Timeline. Он
выступает контейнером, который управляет запуском вложенных
анимаций.
const circle = new mojs.Shape({
shape: 'circle',
fill: 'none',
stroke: 'white',
strokeWidth: 4,
radius: 40,
duration: 1000
});
const square = new mojs.Shape({
shape: 'rect',
fill: 'none',
stroke: 'cyan',
strokeWidth: 4,
radius: 30,
duration: 1000
});
const timeline = new mojs.Timeline();
timeline.add(circle, square);
timeline.play();
В этом случае оба объекта запускаются одновременно, так как добавлены в одну временную ось без дополнительных смещений.
Ключевой механизм синхронизации — общая временная шкала, где
duration каждого элемента сопоставляется с началом
таймлайна.
Для создания сложной координации используется параметр
delay, позволяющий сдвигать старт отдельных объектов
относительно начала таймлайна.
const circle = new mojs.Shape({
shape: 'circle',
radius: 30,
fill: 'none',
stroke: 'white',
duration: 800
});
const line = new mojs.Shape({
shape: 'line',
stroke: 'yellow',
strokeWidth: 6,
duration: 800,
delay: 300
});
const burst = new mojs.Burst({
radius: { 0: 80 },
count: 6,
children: {
shape: 'circle',
radius: 6,
fill: 'orange'
},
delay: 600
});
new mojs.Timeline().add(circle, line, burst).play();
Здесь формируется каскад событий: сначала запускается круг, затем линия, затем взрыв частиц. Такой подход используется для построения сцен с визуальным ритмом.
При синхронизации нескольких объектов важно учитывать их
duration, чтобы избежать рассинхронизации фаз анимации.
const baseDuration = 1000;
const ring = new mojs.Shape({
shape: 'circle',
radius: 50,
stroke: 'white',
fill: 'none',
duration: baseDuration
});
const ring2 = new mojs.Shape({
shape: 'circle',
radius: 70,
stroke: 'cyan',
fill: 'none',
duration: baseDuration
});
Идентичные длительности позволяют объектам завершать анимацию одновременно, создавая эффект композиционного единства.
Для множества однотипных объектов применяется техника ступенчатого запуска через вычисление задержек.
const shapes = [];
for (let i = 0; i < 10; i++) {
shapes.push(
new mojs.Shape({
shape: 'circle',
radius: 10,
fill: 'white',
duration: 600,
delay: i * 80
})
);
}
const timeline = new mojs.Timeline().add(...shapes);
timeline.play();
Каждый следующий объект получает увеличенную задержку, формируя эффект волны. Это особенно эффективно при построении визуальных потоков или реактивных интерфейсов.
mo.js предоставляет событийную модель, позволяющую связывать запуск объектов по завершении других анимаций.
const first = new mojs.Shape({
shape: 'circle',
radius: 40,
stroke: 'white',
duration: 800
});
const second = new mojs.Shape({
shape: 'rect',
radius: 30,
stroke: 'cyan',
duration: 800,
isShowStart: false
});
first
.then(second)
.play();
Метод then создаёт цепочку исполнения, где следующий
объект стартует строго после завершения предыдущего. Это используется
для линейных сценариев с детерминированной последовательностью.
При усложнении сцен отдельные группы анимаций объединяются в подтаймлайны.
const groupA = new mojs.Timeline();
const groupB = new mojs.Timeline();
groupA.add(
new mojs.Shape({ shape: 'circle', radius: 20, duration: 500 }),
new mojs.Shape({ shape: 'circle', radius: 30, duration: 500, delay: 100 })
);
groupB.add(
new mojs.Shape({ shape: 'rect', radius: 25, duration: 500 }),
new mojs.Shape({ shape: 'rect', radius: 35, duration: 500, delay: 100 })
);
const master = new mojs.Timeline();
master.add(groupA, groupB);
master.play();
Такой подход позволяет изолировать группы анимаций, сохраняя глобальную синхронизацию на уровне мастер-таймлайна.
Сложные сцены часто требуют унификации параметров нескольких объектов: одинаковых скоростей, easing-функций и фаз.
const easing = mojs.easing.cubic.out;
const a = new mojs.Shape({
shape: 'circle',
radius: { 0: 40 },
easing,
duration: 900
});
const b = new mojs.Shape({
shape: 'rect',
radius: { 0: 40 },
easing,
duration: 900
});
Единый набор параметров обеспечивает визуальную согласованность даже при независимом управлении объектами.
Объекты могут запускаться от одного внешнего события, обеспечивая жёсткую синхронизацию.
const burst = new mojs.Burst({
radius: { 0: 100 },
count: 8,
children: {
shape: 'circle',
fill: 'white',
radius: 5
}
});
const ring = new mojs.Shape({
shape: 'circle',
radius: 60,
stroke: 'white',
fill: 'none'
});
document.addEventListener('click', () => {
burst.replay();
ring.replay();
});
В этом случае синхронность достигается не через таймлайн, а через единый триггер события, что особенно полезно для интерактивных интерфейсов.
При наложении анимаций важную роль играет управление фазами старта и завершения. Перекрытие создаёт ощущение непрерывного движения.
const a = new mojs.Shape({
shape: 'circle',
radius: 40,
duration: 1000
});
const b = new mojs.Shape({
shape: 'circle',
radius: 60,
duration: 1000,
delay: 500
});
new mojs.Timeline().add(a, b).play();
Перекрытие в 50% длительности формирует эффект эстафеты между объектами.
При создании адаптивных сцен параметры могут вычисляться в рантайме, что требует согласованного пересчёта всех зависимых объектов.
const base = 800;
const factor = 1.2;
const a = new mojs.Shape({
shape: 'circle',
duration: base
});
const b = new mojs.Shape({
shape: 'circle',
duration: base * factor,
delay: base * 0.3
});
Такая модель используется для масштабируемых интерфейсов, где временные зависимости сохраняются при изменении общей скорости сцены.
Сложные композиции строятся по принципу многоуровневой иерархии: отдельные анимации → группы → мастер-таймлайн. Каждый уровень управляет только своей частью временной шкалы, передавая контроль выше.
Такой подход снижает связанность и позволяет масштабировать анимационные сцены без потери контроля над временными зависимостями.