Комбинирование с другими модулями

mo.js строится вокруг модульной системы, в которой каждая анимационная сущность представляет собой самостоятельный объект: tween, shape, burst, timeline или custom module. Комбинирование этих сущностей позволяет выстраивать сложные анимационные сцены, синхронизировать поведение элементов и создавать составные эффекты без монолитной логики.

В основе подхода лежит принцип композиции: сложные анимации формируются из простых независимых блоков. Каждый модуль выполняет строго ограниченную функцию, а взаимодействие между ними осуществляется через:

  • временные шкалы (timelines)
  • события жизненного цикла
  • общие параметры прогресса
  • вложенные анимации

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

Композиция tween-объектов

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 и Tween

Shape-модули (circle, rect, polygon и другие) изначально предназначены для декларативной анимации, но их можно объединять с tween для расширения логики.

Управление shape через внешние 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 как композиционный элемент

Burst-модули создают набор однотипных частиц, которые сами по себе являются мини-анимациями. Их особенно эффективно комбинировать с timeline и пользовательскими tween.

Синхронизация burst с другими эффектами

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 может содержать другие 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();

Такой подход позволяет:

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

Комбинирование с DOM-анимациями

mo.js часто используется вместе с прямыми манипуляциями DOM через requestAnimationFrame или CSS transitions. Это требует синхронизации прогресса между системами.

Синхронизация с 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 классами

В сложных интерфейсах часть анимации выносится в CSS:

const tween = new mojs.Tween({
  duration: 400,
  onComplete: () => {
    element.classList.add('active-state');
  }
});

Такое разделение позволяет комбинировать производительность CSS и гибкость JS-анимаций.

Интеграция с внешними анимационными библиотеками

Комбинирование mo.js с другими системами анимации строится на принципе разделения зон ответственности.

Совместное использование с GSAP

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();

Такая архитектура обеспечивает расширяемость системы без изменения ядра.

Оркестрация сложных сцен

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

  • Burst формирует визуальный всплеск
  • Shape создаёт основную форму
  • Tween управляет интерфейсными элементами
  • Timeline координирует порядок выполнения
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();

Такой подход позволяет строить сложные визуальные сценарии из независимых компонентов без потери управляемости и читаемости кода.