Easing для участков кривой

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

В основе лежит трансформация параметра времени t ∈ [0, 1], который подаётся на вход easing-функции и преобразуется в значение прогресса анимации:

  • линейное движение соответствует f(t) = t
  • нелинейное движение задаётся кривыми Безье или предустановленными функциями

В mo.js easing может задаваться:

  • строковыми ключами ("quad.in", "cubic.out", "expo.inout")
  • массивами кубических Безье [x1, y1, x2, y2]
  • пользовательскими функциями

Ключевой особенностью является то, что easing применяется на уровне конкретного tween или сегмента timeline, а не глобально.


Сегментирование временной кривой

При построении сложной анимации единый easing часто оказывается недостаточным. Поведение объекта требуется менять по фазам:

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

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

Пример логического разбиения:

0.0 ──── 0.3 ──── 0.7 ──── 1.0
  A        B        C

Где:

  • A — стартовое ускорение
  • B — основная инерция
  • C — торможение

Локальный easing в timeline mo.js

В mo.js timeline позволяет комбинировать несколько tween-объектов, каждый из которых имеет собственную временную длительность и easing:

const timeline = new mojs.Timeline();

const tweenA = new mojs.Tween({
  duration: 300,
  easing: 'quad.out'
});

const tweenB = new mojs.Tween({
  duration: 500,
  easing: 'linear'
});

const tweenC = new mojs.Tween({
  duration: 200,
  easing: 'expo.in'
});

timeline.add(tweenA, tweenB, tweenC);
timeline.play();

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


Интерпретация сегментного easing как композиции функций

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

F(t) = Fi(t), t ∈ [ti, ti+1]

где:

  • Fi — easing-функция конкретного сегмента
  • границы ti задают разбиение timeline

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


Кубические кривые Безье как основа сегментов

Большинство easing-функций в mo.js сводятся к кубической кривой Безье:

easing: [0.25, 0.1, 0.25, 1.0]

Каждая такая кривая задаёт характер ускорения:

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

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


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

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

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

Это приводит к эффектам:

  • резкий скачок ускорения
  • “ломаное” движение
  • инерционные артефакты

Для минимизации используются два подхода:

  1. синхронизация конечного значения предыдущего сегмента с началом следующего
  2. подбор easing-пар, где производные в точке стыка близки

Каскадные easing-переходы

Сложные анимации часто используют каскадную модель:

segment 1 → ease-out
segment 2 → ease-in-out
segment 3 → ease-in

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


Применение сегментного easing в shape-анимации

В mo.js shape-анимациях easing может управлять не только позицией, но и параметрами формы:

const shape = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 80 },
  duration: 1000,
  easing: 'cubic.out'
});

При разбиении на сегменты можно независимо управлять:

  • радиусом
  • прозрачностью
  • поворотом
  • масштабом

Каждое свойство может иметь собственную сегментную кривую времени, что приводит к многомерному easing-пространству.


Синхронизация нескольких easing-каналов

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

  • opacity может использовать expo.in
  • scale — back.out
  • rotation — linear

Несовпадение сегментов создаёт асинхронное поведение, которое может быть как художественным приёмом, так и ошибкой композиции.

Для строгой синхронизации используется:

  • единый timeline
  • одинаковое разбиение на сегменты
  • привязка длительностей через коэффициенты

Эффект “физической правдоподобности” через сегменты easing

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

  • ускорение под действием силы
  • инерционное движение
  • сопротивление среды

Типичная модель:

  1. ускорение: quad.in
  2. инерция: linear
  3. торможение: cubic.out

Такое разделение создаёт ощущение массы и инерции без использования физического движка.


Комбинирование easing с path-анимацией

При движении по кривой (motion path) easing управляет не геометрией пути, а параметром прогресса вдоль него:

progress → easing(progress) → position on path

Сегментация здесь позволяет:

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

Практика построения составных easing-кривых

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

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

Типовой шаблон:

const t1 = new mojs.Tween({ duration: 200, easing: 'quad.out' });
const t2 = new mojs.Tween({ duration: 600, easing: 'linear' });
const t3 = new mojs.Tween({ duration: 300, easing: 'expo.in' });

new mojs.Timeline().add(t1, t2, t3).play();

Такой подход превращает easing из локальной функции в структурный элемент архитектуры анимации.


Взаимодействие easing и задержек между сегментами

Между tween-сегментами могут присутствовать паузы, которые влияют на восприятие кривой времени:

  • отсутствие задержки создаёт непрерывную кривую
  • наличие задержки создаёт “разрыв” динамики

Комбинация delay и easing используется для имитации:

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

Многослойная композиция easing-кривых

Сложные интерфейсные анимации используют несколько уровней сегментации:

  • глобальный timeline
  • локальные tween-сегменты
  • вложенные easing-функции для отдельных свойств

В результате формируется иерархическая модель:

timeline
 ├── segment A (ease-out)
 ├── segment B (ease-in-out)
 │     ├── opacity easing
 │     ├── transform easing
 └── segment C (ease-in)

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