Композиция сложных эффектов

Композиция эффектов в библиотеке mo.js строится на объединении нескольких анимационных объектов в единое синхронизированное поведение. Базовыми строительными блоками выступают классы Shape, ShapeSwirl, Burst, Html, а также таймлайны (Timeline), позволяющие координировать сложные сценарии.

Ключевая идея — разделение анимации на независимые элементы с последующим управлением их взаимодействием через общие временные параметры.


Таймлайны как основа сложных эффектов

Timeline объединяет несколько анимаций в одну структуру:

const timeline = new mojs.Timeline();

const circle = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 50 },
  fill: 'red',
  duration: 500
});

const rect = new mojs.Shape({
  shape: 'rect',
  radius: { 0: 40 },
  fill: 'blue',
  duration: 500
});

timeline.add(circle, rect);
timeline.play();

Особенности:

  • Все добавленные анимации запускаются синхронно
  • Можно задавать задержки (delay) для каждого элемента
  • Таймлайн можно переиспользовать и контролировать (pause, replay)

Последовательная композиция

Для создания последовательных эффектов используется смещение по времени:

const timeline = new mojs.Timeline();

const first = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 30 },
  duration: 400
});

const second = new mojs.Shape({
  shape: 'rect',
  radius: { 0: 30 },
  delay: 400,
  duration: 400
});

timeline.add(first, second).play();

Подход:

  • Каждая следующая анимация получает delay, равный длительности предыдущей
  • Формируется цепочка эффектов

Параллельно-последовательные структуры

Комбинирование параллельных и последовательных элементов позволяет создавать более сложные сценарии:

const timeline = new mojs.Timeline();

const burst = new mojs.Burst({
  radius: { 0: 100 },
  count: 10,
  duration: 600
});

const circle = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 50 },
  delay: 300,
  duration: 500
});

timeline.add(burst, circle).play();

Здесь:

  • Burst начинается сразу
  • Shape стартует в середине первой анимации

Использование stagger-эффектов

Повторяющиеся элементы можно анимировать с небольшими задержками:

const burst = new mojs.Burst({
  count: 5,
  radius: { 0: 80 },
  children: {
    shape: 'circle',
    delay: 'stagger(100)',
    duration: 400
  }
});

burst.play();

Результат:

  • Каждый элемент появляется с интервалом
  • Возникает эффект волны или каскада

Вложенные композиции

Анимации могут включать другие анимации как логические группы:

const innerTimeline = new mojs.Timeline();
innerTimeline.add(
  new mojs.Shape({ radius: { 0: 20 }, duration: 300 }),
  new mojs.Shape({ radius: { 20: 0 }, duration: 300, delay: 300 })
);

const mainTimeline = new mojs.Timeline();
mainTimeline.add(innerTimeline).play();

Преимущества:

  • Повторное использование групп
  • Логическая изоляция сложных эффектов

Синхронизация через параметры easing

Композиция становится выразительнее при согласовании кривых ускорения:

const shape1 = new mojs.Shape({
  radius: { 0: 50 },
  easing: 'cubic.out'
});

const shape2 = new mojs.Shape({
  radius: { 0: 50 },
  easing: 'elastic.out'
});

Комбинирование:

  • плавные (cubic) + упругие (elastic)
  • линейные + резкие (back, bounce)

Контраст easing-функций усиливает визуальный эффект.


Связь параметров между объектами

mo.js позволяет синхронизировать параметры:

const base = new mojs.Shape({
  radius: { 0: 50 }
});

const dependent = new mojs.Shape({
  radius: { 0: base.radius },
  delay: 200
});

Чаще используется косвенно через одинаковые значения:

  • одинаковая длительность
  • единый центр (x, y)
  • общие цвета

Централизация координат

Для сложных эффектов важно управлять общей точкой:

const x = 200;
const y = 200;

const burst = new mojs.Burst({ x, y });
const circle = new mojs.Shape({ x, y });

new mojs.Timeline().add(burst, circle).play();

Это создаёт ощущение единого события.


Работа с трансформациями

Композиция часто строится вокруг комбинации transform-свойств:

new mojs.Shape({
  scale: { 0: 1 },
  rotate: { 0: 180 },
  opacity: { 1: 0 }
});

Комбинации:

  • scale + opacity → появление/исчезновение
  • rotate + translate → динамическое движение
  • skew + scale → искажение

Управление временем жизни эффектов

Сложные композиции требуют контроля:

  • duration — длительность
  • delay — задержка
  • repeat — повтор
  • yoyo — обратное воспроизведение
new mojs.Shape({
  radius: { 0: 50 },
  duration: 500,
  repeat: 2,
  yoyo: true
});

Динамическое создание эффектов

Композиция может строиться программно:

const timeline = new mojs.Timeline();

for (let i = 0; i < 5; i++) {
  timeline.add(new mojs.Shape({
    x: i * 20,
    delay: i * 100,
    radius: { 0: 20 }
  }));
}

timeline.play();

Преимущества:

  • масштабируемость
  • генерация паттернов
  • параметризация

Комбинация Burst и Shape

Часто используется для создания “взрывов”:

const burst = new mojs.Burst({
  count: 8,
  radius: { 0: 100 }
});

const center = new mojs.Shape({
  radius: { 0: 30 },
  fill: 'yellow',
  duration: 400
});

new mojs.Timeline().add(burst, center).play();

Логика:

  • центральный объект
  • радиальное распространение

Реактивные композиции (события)

Эффекты могут запускаться по событиям:

document.addEventListener('click', (e) => {
  new mojs.Burst({
    x: e.pageX,
    y: e.pageY
  }).play();
});

Добавление нескольких эффектов создаёт сложную реакцию:

document.addEventListener('click', (e) => {
  const timeline = new mojs.Timeline();

  timeline.add(
    new mojs.Burst({ x: e.pageX, y: e.pageY }),
    new mojs.Shape({ x: e.pageX, y: e.pageY })
  ).play();
});

Переиспользование и модульность

Композиции удобно оформлять в функции:

function createExplosion(x, y) {
  return new mojs.Timeline().add(
    new mojs.Burst({ x, y }),
    new mojs.Shape({ x, y })
  );
}

createExplosion(100, 100).play();

Оптимизация сложных эффектов

При большом количестве элементов важно:

  • уменьшать duration
  • избегать лишних DOM-элементов
  • использовать isShowStart: false
  • группировать анимации в таймлайны

Типовые композиционные паттерны

1. Всплеск (Burst + fade):

  • Burst
  • исчезающий центральный объект

2. Волна:

  • stagger delay
  • одинаковые элементы

3. Пульсация:

  • scale + opacity
  • repeat + yoyo

4. Каскад:

  • последовательные Shape
  • возрастающий delay

Глубокая композиция через несколько таймлайнов

const t1 = new mojs.Timeline().add(
  new mojs.Shape({ radius: { 0: 20 } })
);

const t2 = new mojs.Timeline().add(
  new mojs.Shape({ radius: { 20: 0 } })
);

const master = new mojs.Timeline();
master.add(t1, t2).play();

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

  • разделять ответственность
  • управлять сложными сценариями
  • тестировать части отдельно

Управление состоянием анимации

Методы:

  • play()
  • pause()
  • replay()
  • setProgress()
timeline.setProgress(0.5);

Это даёт возможность:

  • синхронизации с пользовательским вводом
  • создания scrub-анимаций

Комбинирование с CSS и DOM

Html-класс позволяет анимировать реальные элементы:

new mojs.Html({
  el: '#element',
  x: { 0: 100 },
  opacity: { 1: 0 }
}).play();

Композиция может включать:

  • canvas-элементы (Shape)
  • DOM-элементы (Html)

Сложные сценарии с зависимостями

Композиция может учитывать логические зависимости:

  • запуск одной анимации после завершения другой
  • условные ветвления
  • пользовательские триггеры
shape1.then({
  radius: { 50: 0 }
});

Баланс сложности и читаемости

При построении сложных эффектов важно:

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

Композиция в mo.js — это не просто объединение анимаций, а проектирование временной и визуальной структуры, где каждая часть усиливает общую динамику.