В анимационной модели mo.js ключевую роль играет функция
преобразования времени в прогресс анимации. Именно это преобразование
определяет характер движения, ускорения и замедления объектов, делая
визуальные эффекты либо механически линейными, либо органично «живыми».
Кривые изменения задают нелинейное соответствие между нормализованным
временем t ∈ [0, 1] и значением прогресса
p ∈ [0, 1], влияя на динамику любого tween или
shape-анимации.
В основе большинства механизмов лежит идея easing-функции. В простейшем случае прогресс совпадает со временем, и анимация движется равномерно. Однако визуально более сложные сценарии требуют иного поведения: ускорения в начале, замедления в конце, резких рывков или колебаний. Кривые изменения формируют эту нелинейность.
Линейная интерполяция задаётся функцией:
p(t) = t
Такой подход даёт равномерное движение без ускорений и замедлений. В контексте интерфейсной анимации это часто воспринимается как «неестественное» поведение, поскольку физические процессы редко происходят строго линейно. Даже простое движение объекта обычно имеет фазу разгона и торможения.
В mo.js линейная кривая может быть задана явно:
new mojs.Tween({
duration: 1000,
easing: 'linear'
});
Несмотря на простоту, линейная функция часто используется как базовая точка для сравнения поведения других кривых.
Наиболее распространённый тип кривых изменения основан на кубических кривых Безье. Они задаются четырьмя точками: начальной, конечной и двумя контрольными, формирующими форму изгиба.
Математически кривая определяется как:
B(t) = (1 - t)^3 P0 + 3(1 - t)^2 t P1 + 3(1 - t) t^2 P2 + t^3 P3
В контексте easing фиксируются P0 = (0,0) и P3 = (1,1), а контрольные точки P1 и P2 задают характер ускорения.
В mo.js это выражается строкой:
new mojs.Tween({
duration: 1200,
easing: 'cubic.out'
});
или пользовательской кривой:
new mojs.Tween({
duration: 1200,
easing: 'cubic-bezier(0.25, 0.1, 0.25, 1)'
});
Контроль формы кривой позволяет управлять «ощущением» движения: резкий старт, мягкое завершение или наоборот.
Поведение easing-функций обычно делится на три базовых категории: ускорение (ease-in), замедление (ease-out) и комбинацию обоих эффектов (ease-in-out).
Функция ускорения характеризуется малым приростом в начале и увеличением скорости ближе к концу:
easing: 'quad.in'
Замедление действует наоборот — быстрый старт и плавное завершение:
easing: 'quad.out'
Комбинированное поведение создаёт симметричную кривую:
easing: 'quad.in-out'
Такие формы используются для имитации физических процессов, где объект сначала преодолевает инерцию, затем постепенно останавливается.
Помимо Безье-кривых, в mo.js применяются математические функции, описывающие более сложные динамики.
Экспоненциальное затухание:
easing: 'expo.out'
Функция такого типа может быть описана как:
p(t) = 1 - 2^{-10t}
Сильное ускорение в начале и почти мгновенное насыщение в конце создаёт эффект резкого завершения движения.
Синусоидальные кривые:
easing: 'sin.in-out'
Такие функции задают плавные колебательные изменения скорости:
p(t) = 0.5 * (1 - cos(πt))
Они часто применяются для мягких переходов, где требуется отсутствие резких скачков ускорения.
Одной из наиболее мощных возможностей mo.js является использование SVG-путей для задания easing-функций. Кривая задаётся строкой path, интерпретируемой как траектория функции времени.
new mojs.Tween({
duration: 1500,
easing: 'M0,0 C0.2,0.8 0.2,1 1,1'
});
Такой подход позволяет строить произвольные кривые изменения, выходящие за рамки стандартных математических функций. SVG path интерпретируется как карта соответствия времени и прогресса, где координата X — нормализованное время, а Y — значение прогресса.
Преимущество такого подхода заключается в визуальном проектировании кривой: форма может быть создана графически и затем использована в анимации без аналитического описания.
Любая кривая изменения в конечном итоге сводится к вычислению значения прогресса на каждом кадре анимации. Это означает, что непрерывная функция дискретизируется с частотой кадров рендера.
Процесс можно описать следующим образом:
Нормализация времени:
t = elapsed / durationВычисление значения кривой:
p = easing(t)Интерполяция свойств объекта:
value = start + (end - start) * pКачество анимации напрямую зависит от стабильности вычисления
p(t) и поведения кривой на отрезке [0,1].
В mo.js кривые изменения часто применяются не к одному параметру, а сразу к нескольким свойствам анимации. Например, положение, масштаб и прозрачность могут использовать разные easing-функции.
new mojs.Html({
el: '.box',
x: { 0: 200, easing: 'expo.out' },
scale: { 1: 0.5, easing: 'quad.in-out' },
opacity: { 0: 1, easing: 'linear' }
});
Такой подход создаёт многослойную динамику, где объект одновременно перемещается, изменяет размер и проявляется с разной скоростью.
Кривые изменения тесно связаны с понятием временной шкалы. В mo.js таймлайн позволяет синхронизировать несколько анимаций, каждая из которых имеет собственную кривую поведения.
При наложении нескольких tween-эффектов с разными easing-функциями возникает сложная результирующая динамика, которая воспринимается как единое движение с внутренней структурой.
Пример:
const timeline = new mojs.Timeline();
timeline.add(
new mojs.Tween({
duration: 1000,
easing: 'quad.out'
}),
new mojs.Tween({
duration: 1000,
delay: 200,
easing: 'expo.out'
})
);
Разные кривые формируют разную плотность движения во времени, создавая эффект «слоистой» анимации.
Человеческое восприятие скорости нелинейно, поэтому линейные кривые часто воспринимаются как механические. Кривые изменения компенсируют эту особенность восприятия.
Эксперименты с easing показывают, что:
Таким образом, форма кривой напрямую влияет не только на математику анимации, но и на психологическое восприятие интерфейса.
Разные типы объектов требуют различных кривых:
quad.in-outback.outexpo.inlinearВыбор кривой определяет характер взаимодействия между пользователем и интерфейсом, формируя ощущение отзывчивости или плавности среды.
При использовании пользовательских SVG-кривых важно учитывать вычислительную стабильность. Слишком сложные формы могут приводить к артефактам интерполяции или неравномерному распределению скорости.
Также критичным является соблюдение диапазона [0,1] по обеим осям, поскольку выход за пределы нарушает корректность интерпретации прогресса и может приводить к визуальным скачкам.
Кривые изменения в mo.js выступают не просто параметром анимации, а механизмом управления общей динамикой сцены. Через них формируется ритм, плотность движения и визуальная структура интерфейса.
Комбинация разных типов кривых в пределах одной сцены позволяет создавать сложные хореографические последовательности, где каждый элемент движется по собственной временной логике, но остаётся синхронизированным с общей системой анимации.