Сложные траектории движения

Сложные траектории в mo.js строятся вокруг привязки анимации к геометрии пути. На практике используется SVG path, который задаёт кривую любой сложности: от простых дуг до многоузловых сплайнов с резкими перегибами.

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

Типовая структура SVG-пути:

const path = "M0,0 C150,200 300,-100 500,0";

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

В mo.js подобные траектории используются через привязку объекта к пути:

const shape = new mojs.Shape({
  shape: 'circle',
  radius: 10,
  fill: '#4FC3F7',

  // движение по траектории
  path: 'M0,0 C150,200 300,-100 500,0',

  duration: 3000,
  easing: 'linear'
});

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


Декомпозиция сложного движения на сегменты

Сложные траектории редко реализуются одной кривой. Более управляемый подход — разбиение движения на сегменты с разными параметрами.

Каждый сегмент может иметь:

  • собственную кривую пути
  • независимую длительность
  • локальный easing
  • изменение масштаба или вращения

Пример сегментированной анимации:

const segment1 = new mojs.Shape({
  shape: 'circle',
  radius: 8,
  fill: '#FF5252',

  path: 'M0,0 C100,150 200,150 300,0',
  duration: 1200,
  easing: 'cubic.out'
});

const segment2 = new mojs.Shape({
  shape: 'circle',
  radius: 8,
  fill: '#FF5252',

  path: 'M300,0 C400,-150 500,150 600,0',
  duration: 1200,
  easing: 'bounce.out'
});

Последовательное воспроизведение таких сегментов позволяет строить траектории с резкими сменами направления, имитируя физические эффекты: отскоки, падения, инерцию.


Использование временных смещений и таймлайна

mo.js предоставляет механизм Timeline, который позволяет синхронизировать несколько траекторий в единой временной шкале. Это критично при построении сложных систем движения, где один объект влияет на другой.

const timeline = new mojs.Timeline();

timeline.add(segment1, segment2);

timeline.play();

При использовании таймлайна появляется возможность:

  • вводить задержки между сегментами
  • накладывать движения друг на друга
  • формировать каскадные траектории
  • синхронизировать вращение и масштаб с перемещением

Особенно эффективно это работает при моделировании «разлета» объектов по разным направлениям после общей точки старта.


Кривые Безье как инструмент управления ускорением

Траектория в mo.js фактически является функцией положения, но ощущение «физики» создаётся за счёт формы кривой.

Кубическая Безье позволяет управлять ускорением без явного задания velocity:

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

Пример «инерционной дуги»:

const path = "M0,0 C50,300 450,300 500,0";

Такая форма создаёт эффект разгона с последующим плавным возвратом.

Для более сложных сценариев используется цепочка кривых:

const path =
  "M0,0 C100,200 200,200 300,0 C400,-200 500,-200 600,0";

Каждый сегмент управляет локальной динамикой движения, создавая ощущение многослойной физики.


Поворот по касательной к траектории

Одним из ключевых элементов реалистичных траекторий является ориентация объекта по направлению движения. В mo.js это реализуется через вычисление касательной к пути.

Идея заключается в том, что угол объекта совпадает с производной кривой:

  • при движении вверх объект поворачивается вверх
  • при повороте траектории — синхронно вращается
  • при резких изгибах создаётся эффект «реакции массы»

Пример конфигурации:

const shape = new mojs.Shape({
  shape: 'rect',
  radiusX: 10,
  radiusY: 4,
  fill: '#FFF176',

  path: 'M0,0 C200,200 400,-200 600,0',

  isShowStart: true,
  isShowEnd: true,

  angle: { 0: 360 },

  duration: 2500
});

Хотя явного параметра “align to path” может не быть в базовой конфигурации, эффект достигается через синхронизацию вращения с прогрессом движения и расчёт угловой динамики.


Наложение нескольких траекторий

Сложные визуальные эффекты возникают при одновременном использовании нескольких независимых путей для одного объекта.

Подход заключается в разделении движения на компоненты:

  • основная траектория (X/Y)
  • колебания (sinusoidal offset)
  • микросмещения (noise)
  • вращение вокруг центра траектории

Пример комбинированного движения:

const main = new mojs.Shape({
  shape: 'circle',
  radius: 10,
  fill: '#29B6F6',

  path: 'M0,0 C200,100 400,-100 600,0',
  duration: 3000
});

const wobble = new mojs.Tween({
  duration: 3000,
  repeat: 999,
  onUpdate: (p) => {
    const offset = Math.sin(p * Math.PI * 10) * 10;
    // применение смещения к основной позиции
  }
});

Такой подход позволяет имитировать:

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

Использование полярных координат для радиальных траекторий

Помимо SVG путей часто применяется полярная система координат. Она особенно эффективна для радиальных и спиральных движений.

Основная модель:

  • угол увеличивается во времени
  • радиус изменяется по функции ускорения

Пример спиральной траектории:

const spiral = new mojs.Shape({
  shape: 'circle',
  radius: 6,
  fill: '#AB47BC',

  duration: 2000,
  easing: 'linear',

  onUpdate: (p) => {
    const angle = p * Math.PI * 10;
    const radius = 20 + p * 200;

    const x = Math.cos(angle) * radius;
    const y = Math.sin(angle) * radius;

    // установка позиции
    // el.style.transform = `translate(${x}px, ${y}px)`
  }
});

Такая схема используется для:

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

Имитация физики через кривые и тайминг

Хотя mo.js не является физическим движком, поведение траекторий можно приближать к физике через комбинацию:

  • нелинейных easing-функций
  • сегментированных путей
  • изменения длительности
  • модификации амплитуды

Пример «гравитационного падения»:

const fall = new mojs.Shape({
  shape: 'circle',
  radius: 8,
  fill: '#EF5350',

  path: 'M0,0 C50,100 100,300 150,600',
  duration: 1800,
  easing: 'quad.in'
});

Ключевой эффект достигается за счёт ускоряющегося easing, который усиливает ощущение падения.


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

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

  • геометрическая система (SVG path)
  • временная система (timeline)
  • система вариаций (noise / randomness)
  • система ориентации (rotation alignment)
  • система вторичных колебаний

Пример объединения:

const base = new mojs.Shape({
  shape: 'circle',
  radius: 12,
  fill: '#66BB6A',
  path: 'M0,0 C150,200 300,-200 450,0',
  duration: 4000
});

const secondary = new mojs.Tween({
  duration: 4000,
  repeat: 999,
  onUpdate: (p) => {
    const jitterX = Math.sin(p * 30) * 3;
    const jitterY = Math.cos(p * 25) * 3;

    // добавление микро-колебаний к базовой траектории
  }
});

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


Управление плотностью и визуальной сложностью траекторий

При увеличении количества объектов движение начинает восприниматься как единая система. В этом случае важна не только форма пути, но и распределение фаз:

  • стартовые задержки (stagger)
  • различие длительности
  • случайные отклонения пути
  • вариативность масштаба

Пример распределённого запуска:

const shapes = [];

for (let i = 0; i < 20; i++) {
  shapes.push(
    new mojs.Shape({
      shape: 'circle',
      radius: 5,
      fill: '#42A5F5',

      path: 'M0,0 C200,100 400,-100 600,0',
      duration: 3000 + Math.random() * 1000,
      delay: i * 50
    })
  );
}

В результате появляется эффект «потока» или «облака частиц», где каждая траектория индивидуальна, но подчинена общей геометрии движения.