Cubic bezier функции

Кривые Безье третьей степени представляют собой параметрические кривые, определяемые четырьмя контрольными точками и широко используемые для описания функций сглаживания анимаций. В контексте mo.js они применяются как основа кастомных easing-функций, позволяющих управлять динамикой движения объектов с высокой точностью.

Функция задаётся через четыре точки: P0, P1, P2, P3. При этом P0 и P3 фиксируют начало и конец кривой, а P1 и P2 управляют её формой.

Параметрическое уравнение:

x(t) = (1 - t)^3 * x0 + 3(1 - t)^2 * t * x1 + 3(1 - t) * t^2 * x2 + t^3 * x3 y(t) = (1 - t)^3 * y0 + 3(1 - t)^2 * t * y1 + 3(1 - t) * t^2 * y2 + t^3 * y3

При использовании в easing-функциях обычно принимается:

  • P0 = (0, 0)
  • P3 = (1, 1)

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

Интерпретация в анимации

Ось X соответствует времени (t ∈ [0, 1]), а ось Y — прогрессу анимации. Изменение положения контрольных точек влияет на характер движения:

  • точки ближе к началу оси Y дают резкий старт
  • точки ближе к концу создают эффект замедления
  • симметричное расположение формирует плавное ускорение и замедление

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

Cubic bezier в mo.js

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

Базовый синтаксис:

const tween = new mojs.Tween({
  duration: 1000,
  easing: 'cubic.out'
});

Встроенные варианты:

  • linear
  • quad
  • cubic
  • quart
  • quint
  • bounce
  • elastic

Однако наиболее гибкий вариант — создание собственной кривой.

Создание кастомной cubic bezier кривой

mo.js предоставляет функцию cubicBezier:

const customEasing = mojs.easing.cubicBezier(0.25, 0.1, 0.25, 1);

const tween = new mojs.Tween({
  duration: 1200,
  easing: customEasing
});

Параметры (x1, y1, x2, y2) задают контрольные точки P1 и P2.

Важно учитывать:

  • x1 и x2 должны находиться в диапазоне [0, 1]
  • y1 и y2 могут выходить за пределы диапазона, создавая overshoot-эффекты

Связь с CSS cubic-bezier

Синтаксис совпадает с CSS:

transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);

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

Поведение контрольных точек

Рассмотрение влияния каждой координаты:

x1 — скорость выхода из начального состояния y1 — интенсивность ускорения в начале

x2 — момент замедления y2 — характер торможения перед завершением

Комбинации значений формируют различные типы динамики:

  • резкий старт + плавное завершение
  • плавный старт + резкий финал
  • «пружинящие» эффекты при выходе за пределы 0–1 по Y

Использование в сложных анимациях mo.js

Cubic bezier применяется в твинах и shape-анимациях:

const shape = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 50 },
  duration: 800,
  easing: mojs.easing.cubicBezier(0.2, 0.8, 0.2, 1)
});

Влияние easing проявляется во всех анимируемых свойствах:

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

Декомпозиция движения

Любая анимация с cubic bezier может быть рассмотрена как функция распределения скорости.

Скорость определяется производной кривой:

v(t) = d(y(t))/dt

На практике это означает:

  • резкие участки кривой = высокая скорость изменения свойства
  • пологие участки = визуальная пауза

mo.js интерпретирует это как временную ремаппинг-функцию.

Типовые кривые и их поведение

Стандартные профили:

0.25, 0.1, 0.25, 1 — плавное ускорение и мягкое торможение 0.42, 0, 1, 1 — резкий старт и линейное завершение 0, 0, 0.58, 1 — медленный старт и резкий финиш

Каждая конфигурация формирует различное ощущение «массы» объекта.

Работа с нелинейным временем

Cubic bezier не изменяет физическое время, а изменяет отображаемое время анимации.

Фактически создаётся функция ремаппинга:

t’ = f(t)

где:

  • t — реальное время
  • t’ — модифицированный прогресс

Это позволяет синхронизировать несколько анимаций с разными динамическими характеристиками, сохраняя единый временной диапазон.

Композиция easing-функций

В mo.js возможно комбинирование нескольких анимаций с разными bezier-кривыми:

const move = new mojs.Tween({
  duration: 1000,
  easing: mojs.easing.cubicBezier(0.1, 0.7, 0.3, 1)
});

const fade = new mojs.Tween({
  duration: 1000,
  easing: mojs.easing.cubicBezier(0.4, 0, 0.2, 1)
});

Несовпадение кривых приводит к расслоению движения:

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

Ограничения и особенности интерполяции

При слишком агрессивных значениях контрольных точек возможны:

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

Особенно критичны значения y1 или y2 вне диапазона [-1, 2], создающие экстремальные overshoot-эффекты.

Практическое применение в интерфейсной анимации

Cubic bezier используется для:

  • анимации появления UI-элементов
  • микровзаимодействий кнопок
  • переходов между состояниями компонентов
  • синхронизации нескольких tween-процессов

В UI-анимации ключевым становится не геометрия движения, а распределение скорости, задаваемое кривой.