mo.js строится вокруг модульной системы, в которой каждая анимационная сущность представляет собой самостоятельный объект: tween, shape, burst, timeline или custom module. Комбинирование этих сущностей позволяет выстраивать сложные анимационные сцены, синхронизировать поведение элементов и создавать составные эффекты без монолитной логики.
В основе подхода лежит принцип композиции: сложные анимации формируются из простых независимых блоков. Каждый модуль выполняет строго ограниченную функцию, а взаимодействие между ними осуществляется через:
Такой подход устраняет необходимость в централизованном управлении всей сценой и позволяет масштабировать анимационные системы без усложнения кода.
Tween в mo.js представляет базовую анимационную единицу, которую можно комбинировать с другими tween-объектами через последовательность или параллельное выполнение.
Последовательность строится через timeline, где каждый
tween стартует после завершения предыдущего.
const opacityTween = new mojs.Tween({
duration: 300,
onUpdate: (p) => {
element.style.opacity = p;
}
});
const moveTween = new mojs.Tween({
duration: 500,
onUpdate: (p) => {
element.style.transform = `translateX(${p * 200}px)`;
}
});
const timeline = new mojs.Timeline();
timeline.add(opacityTween, moveTween);
timeline.play();
Такой подход используется для построения сцен, где один эффект логически следует за другим: появление → движение → трансформация.
При необходимости синхронного запуска несколько tween добавляются в одну временную ось без задержек:
const timeline = new mojs.Timeline();
timeline.add([
new mojs.Tween({
duration: 600,
onUpdate: (p) => elementA.style.transform = `scale(${p})`
}),
new mojs.Tween({
duration: 600,
onUpdate: (p) => elementB.style.opacity = p
})
]);
timeline.play();
Shape-модули (circle, rect, polygon и другие) изначально предназначены для декларативной анимации, но их можно объединять с tween для расширения логики.
Вместо встроенных анимационных свойств используется внешний контроль параметров:
const circle = new mojs.Shape({
shape: 'circle',
radius: 40,
fill: 'cyan'
});
const controller = new mojs.Tween({
duration: 1000,
onUpdate: (p) => {
circle.setProgress(p);
}
});
circle.play();
controller.play();
Такой метод позволяет синхронизировать shape с любыми внешними событиями или логикой интерфейса.
Burst-модули создают набор однотипных частиц, которые сами по себе являются мини-анимациями. Их особенно эффективно комбинировать с timeline и пользовательскими tween.
const burst = new mojs.Burst({
radius: { 0: 100 },
count: 10,
children: {
shape: 'circle',
fill: 'orange'
}
});
const scaleTween = new mojs.Tween({
duration: 800,
onUpdate: (p) => {
button.style.transform = `scale(${1 + p * 0.2})`;
}
});
const timeline = new mojs.Timeline();
timeline.add(burst, scaleTween);
timeline.play();
Burst в данном случае становится визуальным триггером, а tween — управляющим поведением DOM-элемента.
Одним из ключевых механизмов расширенного комбинирования является вложенность временных шкал. Timeline может содержать другие timeline, формируя иерархическую структуру анимаций.
const innerTimeline = new mojs.Timeline();
innerTimeline.add([
new mojs.Tween({ duration: 200 }),
new mojs.Tween({ duration: 300 })
]);
const outerTimeline = new mojs.Timeline();
outerTimeline.add(innerTimeline);
outerTimeline.play();
Такой подход позволяет:
mo.js часто используется вместе с прямыми манипуляциями DOM через
requestAnimationFrame или CSS transitions. Это требует
синхронизации прогресса между системами.
const tween = new mojs.Tween({
duration: 1000,
onUpdate: (p) => {
element.style.transform = `translateY(${p * 150}px)`;
element.style.opacity = p;
}
});
tween.play();
В сложных интерфейсах часть анимации выносится в CSS:
const tween = new mojs.Tween({
duration: 400,
onComplete: () => {
element.classList.add('active-state');
}
});
Такое разделение позволяет комбинировать производительность CSS и гибкость JS-анимаций.
Комбинирование mo.js с другими системами анимации строится на принципе разделения зон ответственности.
GSAP может управлять временной осью, а mo.js — визуальными эффектами:
const burst = new mojs.Burst({
radius: { 0: 120 },
count: 12
});
gsap.to({}, {
duration: 1,
onStart: () => burst.play()
});
Такой подход применяется, когда требуется более сложная оркестрация сцен, чем предоставляет встроенный timeline.
Каждый модуль mo.js поддерживает события жизненного цикла:
start, update, complete. Эти
события позволяют связывать независимые анимации в единую систему.
const tweenA = new mojs.Tween({
duration: 500,
onComplete: () => tweenB.play()
});
const tweenB = new mojs.Tween({
duration: 500
});
tweenA.play();
При масштабировании системы события заменяются на централизованную диспетчеризацию через timeline.
Одним из мощных подходов является связывание параметров разных модулей через общие переменные прогресса.
let progress = { value: 0 };
const tween = new mojs.Tween({
duration: 1000,
onUpdate: (p) => {
progress.value = p;
}
});
const shape = new mojs.Shape({
shape: 'circle',
radius: () => 20 + progress.value * 30
});
tween.play();
shape.play();
Это создаёт зависимые анимации, где один модуль управляет поведением другого без прямой связи.
mo.js позволяет создавать кастомные анимационные сущности, которые могут комбинироваться с любыми встроенными модулями. Пользовательский модуль реализует интерфейс tween или shape и подключается к timeline как стандартный элемент.
class CustomAnimation extends mojs.CustomShape {
getShape() {
return '<path d="..."/>';
}
}
const custom = new CustomAnimation({
duration: 700
});
const timeline = new mojs.Timeline();
timeline.add(custom);
timeline.play();
Такая архитектура обеспечивает расширяемость системы без изменения ядра.
Комбинирование всех модулей приводит к созданию многоуровневых сцен:
const burst = new mojs.Burst({ count: 8 });
const shape = new mojs.Shape({ shape: 'rect' });
const timeline = new mojs.Timeline();
timeline.add([
burst,
shape,
new mojs.Tween({
duration: 600,
onUpdate: (p) => {
panel.style.opacity = p;
}
})
]);
timeline.play();
Такой подход позволяет строить сложные визуальные сценарии из независимых компонентов без потери управляемости и читаемости кода.