Сложные траектории в 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 используется только для равномерного прохождения пути. Любые изменения скорости внутри траектории реализуются отдельно, через разбиение пути или комбинирование нескольких анимаций.
Сложные траектории редко реализуются одной кривой. Более управляемый подход — разбиение движения на сегменты с разными параметрами.
Каждый сегмент может иметь:
Пример сегментированной анимации:
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” может не быть в базовой конфигурации, эффект достигается через синхронизацию вращения с прогрессом движения и расчёт угловой динамики.
Сложные визуальные эффекты возникают при одновременном использовании нескольких независимых путей для одного объекта.
Подход заключается в разделении движения на компоненты:
Пример комбинированного движения:
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 не является физическим движком, поведение траекторий можно приближать к физике через комбинацию:
Пример «гравитационного падения»:
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, который усиливает ощущение падения.
Наиболее устойчивый подход к построению сложного движения заключается в композиции независимых систем:
Пример объединения:
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;
// добавление микро-колебаний к базовой траектории
}
});
Такой подход позволяет строить визуально сложные системы, которые при этом остаются управляемыми и модульными.
При увеличении количества объектов движение начинает восприниматься как единая система. В этом случае важна не только форма пути, но и распределение фаз:
Пример распределённого запуска:
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
})
);
}
В результате появляется эффект «потока» или «облака частиц», где каждая траектория индивидуальна, но подчинена общей геометрии движения.