Path-based easing в mo.js основан на использовании SVG-пути как функции изменения прогресса анимации, где движение по кривой интерпретируется как временная кривая ускорения. В отличие от классических easing-функций (linear, ease-in, ease-out), здесь поведение анимации определяется геометрией произвольного пути, что позволяет задавать практически неограниченные нелинейные кривые изменения скорости.
Каждый easing в mo.js можно представить как отображение времени t ∈ [0, 1] в значение прогресса p ∈ [0, 1]. В path-based подходе эта функция заменяется траекторией в двумерном пространстве, где:
Таким образом, каждая точка пути задаёт соответствие между моментом времени и степенью выполнения анимации.
Кривая интерпретируется как набор сегментов SVG path (M, L, C, Q и другие), но для easing используется дискретизация: путь преобразуется в последовательность точек, после чего строится функция интерполяции.
SVG-path не является функцией в аналитическом смысле, поэтому mo.js выполняет предварительную обработку:
В результате формируется массив вида:
где t — нормализованное время, p — прогресс анимации.
После дискретизации используется интерполяция для получения плавного перехода между точками. Обычно применяется линейная интерполяция между ближайшими сегментами:
p(t) = p_i + (p_{i+1} - p_i) * (t - t_i) / (t_{i+1} - t_i)
p(t)=p_i + (p_{i+1}-p_i)
Такая схема обеспечивает стабильное поведение даже при сложных кривых с множественными перегибами.
mo.js позволяет передавать SVG path напрямую в качестве easing-функции. Классический пример включает кривую Безье, преобразованную в путь:
Такая форма создаёт ускорение в начале и плавное замедление к концу.
При этом важно учитывать, что координаты должны быть нормализованы: X и Y в диапазоне [0, 1], иначе происходит обрезка или некорректная интерпретация прогресса.
Внутри mo.js easing на основе пути обычно включает три слоя:
Parser отвечает за преобразование строки path в команды. Sampler преобразует команды в массив точек с фиксированным шагом. Interpolator работает на этапе выполнения анимации и возвращает значение прогресса по входному времени.
Такой подход разделяет вычислительно тяжёлую часть (парсинг и семплирование) от runtime-логики.
Любой путь приводится к единичному квадрату. Это критично, поскольку easing-функция должна быть инвариантна к масштабу.
Пусть исходные координаты точки:
(x, y)
После нормализации:
x’ = (x - x_min) / (x_max - x_min) y’ = (y - y_min) / (y_max - y_min)
x’ = , y’ =
Это позволяет гарантировать, что easing всегда укладывается в диапазон от 0 до 1.
Path-based easing поддерживает кривые с:
Однако такие особенности требуют аккуратной дискретизации, поскольку слишком редкая выборка приводит к артефактам.
При увеличении плотности семплирования кривая становится более точной, но возрастает стоимость предварительных вычислений.
В традиционной модели easing время линейно отображается в прогресс:
p = f(t)
В path-based модели функция f(t) задаётся геометрически, но семантически остаётся той же трансформацией временной оси. Это позволяет интегрировать path-easing в любые tween-системы mo.js без изменения основного цикла анимации.
Использование path-based easing особенно заметно в:
Каждый из этих эффектов достигается не изменением ключевых кадров, а изменением формы кривой.
Хотя SVG path может содержать кривые Безье, для easing они всегда приводятся к полилинии. При этом каждая кубическая кривая C разбивается на набор линейных сегментов с контролируемой погрешностью.
Чем выше число сегментов, тем ближе поведение easing к исходной кривой Безье.
Поскольку построение path-easing может быть дорогостоящим, mo.js обычно выполняет:
Это снижает нагрузку в runtime, оставляя только O(1) доступ к значениям прогресса.
Несмотря на гибкость, path-based easing имеет ограничения:
Эти особенности делают подход более подходящим для визуальных эффектов, чем для физически точных симуляций.
Особое внимание уделяется участкам t = 0 и t = 1. В этих точках easing обязан возвращать строго 0 и 1 соответственно. При некорректной нормализации пути возможно смещение границ, поэтому применяется принудительное закрепление крайних значений.
Такой подход гарантирует согласованность с системой tween-движка и предотвращает визуальные «дрожания» на старте и конце анимации.