Кривые в mo.js используются как математическое описание изменения значения параметра во времени или как траектория движения объекта в пространстве. В основе лежат функции интерполяции (easing) и SVG-подобные пути, задающие непрерывные линии различной сложности.
Любая кривая в контексте mo.js интерпретируется как функция отображения времени:
t ∈ [0, 1] → value
где:
Такое представление позволяет унифицировать различные типы кривых: от простых линейных интерполяций до сложных траекторий Безье и SVG-path.
Основной математический инструмент описания плавных кривых — кубическая кривая Безье. Она задаётся четырьмя точками:
P0 — начальная точка P1, P2 — контрольные точки P3 — конечная точка
Функция имеет вид:
B(t) = (1-t)^3 P_0 + 3(1-t)^2 t P_1 + 3(1-t)t^2 P_2 + t^3 P_3
В mo.js для easing-логики обычно фиксируются крайние точки:
Остаются только управляющие коэффициенты P1 и P2.
В mo.js кастомная кривая ускорения задаётся через:
mojs.easing.cubicBezier(x1, y1, x2, y2)
где:
Пример:
const customEasing = mojs.easing.cubicBezier(0.25, 0.1, 0.25, 1);
new mojs.Tween({
duration: 1000,
easing: customEasing,
onUpdate: (p) => {
console.log(p);
}
}).play();
Значения координат ограничиваются диапазоном [0, 1], что обеспечивает стабильную нормализацию времени и предсказуемую интерполяцию.
Встроенные кривые представлены как набор заранее определённых функций:
Их синтаксис:
easing: 'cubic.out'
Структура строки:
Режимы:
Более сложный способ задания траекторий основан на SVG path синтаксисе. В mo.js он используется для описания движения объектов вдоль произвольных линий.
Пример:
path: 'M 0 0 C 100 200, 200 0, 300 100'
Каждая команда формирует сегмент общей кривой, которая затем параметризуется по длине.
В mo.js движение вдоль кривой реализуется через модуль MotionPath:
new mojs.Shape({
shape: 'circle',
motionPath: {
path: 'M 0 0 C 50 100, 150 100, 200 0',
align: true,
autoRotate: true
}
}).play();
Параметры:
При работе с SVG path используется преобразование координаты времени t в расстояние вдоль кривой:
s = t × L
где:
Далее происходит обратное преобразование в координаты (x, y) через интерполяцию сегментов.
При использовании timeline каждый tween получает собственную кривую интерполяции, но синхронизируется по общей временной оси.
new mojs.Timeline({
children: [
new mojs.Tween({
duration: 600,
easing: 'quad.out'
}),
new mojs.Tween({
duration: 600,
easing: mojs.easing.cubicBezier(0.42, 0, 0.58, 1)
})
]
}).play();
Кривые в этом контексте управляют не только значением, но и характером синхронизации элементов внутри общей анимационной системы.
Помимо Bezier и SVG-path допускается использование произвольных функций:
easing: (t) => Math.sin(t * Math.PI)
Такая функция должна:
Подобный подход позволяет строить нелинейные модели поведения, включая физические симуляции и реактивные движения.
При рендеринге кривая разбивается на набор дискретных шагов кадровой частоты. Каждый кадр вычисляется отдельно:
valueₙ = f(tₙ)
где tₙ = n / N
При увеличении N возрастает точность аппроксимации, но повышается вычислительная нагрузка.
При наложении нескольких easing-кривых применяется последовательная композиция:
f(g(t))
где:
Такой подход используется при сложных анимациях, где движение и изменение параметров подчинены разным законам кривизны.
Каждая кривая может рассматриваться как отображение единичного интервала на плоскость или в одномерное пространство параметра. В случае SVG-path это становится отображением:
[0,1] → ℝ²
В случае easing:
[0,1] → [0,1]
что обеспечивает совместимость всех типов кривых внутри единой системы mo.js.