Концепция кривых в mo.js

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

Кривые в mo.js можно разделить на две фундаментальные категории:

  • кривые временного изменения (easing curves)
  • кривые пространственного движения (motion/path curves)

Обе категории работают совместно, формируя итоговое поведение анимации.


Easing как базовая форма кривых

Easing-кривые определяют, как значение параметра изменяется от начального к конечному во времени. В mo.js каждая анимация по умолчанию использует easing-функцию, даже если она не указана явно.

Линейное изменение:

new mojs.Tween({
  duration: 1000,
  onUpdate: (progress) => {
    // progress изменяется линейно от 0 до 1
  }
});

Линейность в анимации редко используется напрямую, так как она создаёт механическое и неестественное движение.


Предустановленные easing-кривые

mo.js включает набор стандартных кривых, основанных на классических функциях плавности. Они определяют характер изменения прогресса анимации:

  • linear
  • ease.in
  • ease.out
  • ease.in.out
  • elastic.out
  • bounce.out
  • back.in
  • back.out

Каждая кривая представляет собой математически заданное преобразование интервала [0, 1].

Пример применения:

new mojs.Tween({
  duration: 800,
  easing: 'elastic.out',
  onUpdate: (p) => {
    // p изменяется по нелинейной кривой с "перелётом"
  }
});

Кривые ускорения и замедления

Ease-in

Форма, при которой движение начинается медленно и ускоряется к концу. Математически это выпуклая кривая.

Характер:

  • мягкий старт
  • нарастающая динамика
  • ощущение «разгона»

Ease-out

Противоположный эффект: быстрое начало и плавное торможение.

Характер:

  • резкий старт
  • инерционное замедление
  • визуальная «мягкость завершения»

Ease-in-out

Комбинированная кривая:

  • начало — медленное
  • середина — ускорение
  • конец — замедление

Используется как универсальная базовая форма.


Пользовательские easing-кривые

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

Функциональный easing:

const customEasing = (p) => {
  return Math.pow(p, 3) * Math.sin(p * Math.PI);
};

new mojs.Tween({
  duration: 1000,
  easing: customEasing
});

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


Bézier-кривые как основа easing

Большинство easing-функций в mo.js основаны на кубических Bézier-кривых. Они задаются четырьмя контрольными точками:

  • (0, 0)
  • (x1, y1)
  • (x2, y2)
  • (1, 1)

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

Пример:

easing: 'cubic-bezier(0.25, 0.1, 0.25, 1)'

Смысл параметров:

  • x-координаты определяют распределение времени
  • y-координаты определяют скорость изменения значения

Интерпретация Bézier-кривых в анимации

Кривая фактически задаёт функцию:

  • по оси X — нормализованное время
  • по оси Y — прогресс значения

Это позволяет:

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

Пространственные кривые движения

Помимо временных easing-кривых, mo.js поддерживает движение по траекториям. Это второй тип кривых — геометрические.

Движение по координатной кривой

new mojs.Html({
  el: '.box',
  x: { 0: 300 },
  y: { 0: 200 },
  easing: 'linear'
});

При добавлении сложных зависимостей координат движение перестаёт быть линейным и формирует траекторию.


Кривые пути (motion path)

mo.js поддерживает движение по заранее заданной кривой пути, чаще всего основанной на SVG.

new mojs.Html({
  el: '.dot',
  path: 'M0,0 C100,200 200,-100 300,0',
  duration: 1200
});

Здесь движение определяется не отдельными координатами, а непрерывной кривой Безье.


Безье-пути как основа траекторий

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

  • M — move to (начальная точка)
  • C — cubic Bézier curve
  • S — smooth curve continuation

Кривая интерпретируется как функция положения объекта во времени.


Комбинация easing и motion path

Сложные анимации в mo.js часто строятся на наложении двух уровней кривых:

  • easing управляет скоростью прохождения пути
  • path управляет геометрией движения

Пример эффекта:

  • объект движется по дуге
  • ускоряется в середине
  • замедляется на концах

Кривые в Burst-анимациях

В Burst-модуле mo.js кривые используются для управления разлётом частиц.

new mojs.Burst({
  radius: { 0: 100 },
  count: 10,
  children: {
    shape: 'circle',
    radius: 5,
    easing: 'quad.out'
  }
});

Здесь кривая влияет на:

  • скорость разлёта
  • распределение частиц
  • визуальную плотность эффекта

Амплитудные кривые и деформация

Некоторые эффекты mo.js используют кривые для изменения не только позиции, но и параметров формы:

  • масштаб
  • прозрачность
  • вращение
  • деформация

Пример:

new mojs.Shape({
  shape: 'circle',
  scale: { 0: 1 },
  opacity: { 0: 1 },
  easing: 'elastic.out'
});

Кривая здесь задаёт амплитуду изменения параметров.


Временные кривые в Timeline

mojs.Timeline позволяет синхронизировать несколько анимаций, каждая из которых имеет собственную кривую, но общая временная ось также может быть нелинейной.

const timeline = new mojs.Timeline();

timeline.add(
  new mojs.Tween({ duration: 1000, easing: 'ease.out' }),
  new mojs.Tween({ duration: 500, easing: 'back.out' })
);

Комбинация кривых формирует сложное поведение композиции.


Многослойные кривые поведения

В сложных сценах mo.js кривые накладываются друг на друга:

  • глобальная временная кривая timeline
  • локальная easing-кривая объекта
  • кривая движения (path)
  • кривая изменения параметров (scale, opacity)

Результирующее движение является суперпозицией всех уровней.


Дискретизация кривых и обновление кадров

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

  • 60 FPS → 60 точек в секунду
  • каждый кадр получает значение из функции кривой
  • интерполяция сглаживает переходы

Это позволяет поддерживать производительность при сложных траекториях.


Физическая интерпретация кривых

Кривые mo.js можно интерпретировать как упрощённые физические модели:

  • ease-out — имитация инерции
  • ease-in — моделирование ускорения
  • elastic — пружинная система
  • bounce — столкновение с поверхностью

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