В системах анимации функция плавности (easing) определяет, как
изменяется прогресс анимации во времени. В Motion One параметр easing
влияет на преобразование нормализованного времени t,
где:
t = 0 — начало анимацииt = 1 — завершение анимацииФункция плавности преобразует линейный прогресс в нелинейный, создавая ускорение, замедление, упругость или сложные динамические кривые.
Любая функция плавности сводится к преобразованию:
eased = f(t)
где:
t — входной прогресс (0..1)f(t) — преобразованный прогресс (0..1 или за его
пределами)eased — итоговое значение, применяемое к анимацииMotion One принимает easing как:
(t: number) => numberПоследний вариант используется для создания кастомной логики.
В Motion One можно передать функцию напрямую:
import { animate } from "motion";
animate(
".box",
{ x: 300 },
{
duration: 1,
easing: (t) => t
}
);
Здесь используется линейная функция, где прогресс не изменяется.
Линейная интерполяция:
const linear = (t) => t;
Свойства:
Квадратичные функции создают более естественное движение за счёт изменения скорости.
const easeInQuad = (t) => t * t;
Поведение:
const easeOutQuad = (t) => 1 - (1 - t) * (1 - t);
Поведение:
const easeInOutQuad = (t) =>
t < 0.5
? 2 * t * t
: 1 - Math.pow(-2 * t + 2, 2) / 2;
Поведение:
Кубические функции обеспечивают более выраженную динамику.
const easeInCubic = (t) => t * t * t;
const easeOutCubic = (t) => 1 - Math.pow(1 - t, 3);
const easeInOutCubic = (t) =>
t < 0.5
? 4 * t * t * t
: 1 - Math.pow(-2 * t + 2, 3) / 2;
Кубические кривые:
Функции плавности не обязаны оставаться в пределах
[0, 1]. Это используется для эффектов переразлёта
(overshoot).
const overshoot = (t) => {
const s = 1.70158;
return t * t * ((s + 1) * t - s);
};
Особенности:
Эластичное движение моделирует колебания после достижения цели.
const easeOutElastic = (t) => {
const c4 = (2 * Math.PI) / 3;
return t === 0
? 0
: t === 1
? 1
: Math.pow(2, -10 * t) *
Math.sin((t * 10 - 0.75) * c4) +
1;
};
Свойства:
Bounce-эффект моделирует падение и отскок объекта.
const easeOutBounce = (t) => {
const n1 = 7.5625;
const d1 = 2.75;
if (t < 1 / d1) {
return n1 * t * t;
} else if (t < 2 / d1) {
t -= 1.5 / d1;
return n1 * t * t + 0.75;
} else if (t < 2.5 / d1) {
t -= 2.25 / d1;
return n1 * t * t + 0.9375;
} else {
t -= 2.625 / d1;
return n1 * t * t + 0.984375;
}
};
Характеристики:
Motion One использует easing на уровне каждого свойства анимации:
animate(
".card",
{
scale: [0.8, 1],
opacity: [0, 1]
},
{
duration: 0.6,
easing: easeOutCubic
}
);
При этом функция применяется ко всему прогрессу анимации, а не к отдельным ключам.
Сложные кривые часто строятся через композицию простых функций.
const scaleTime = (easing) => (t) => easing(t * 2 > 1 ? 1 : t * 2);
const invert = (easing) => (t) => 1 - easing(1 - t);
Такие преобразования позволяют:
В последовательных анимациях функции плавности влияют на восприятие ритма:
animate(".item-1", { x: 100 }, { easing: easeOutCubic });
animate(".item-2", { x: 100 }, { easing: easeInOutQuad });
animate(".item-3", { x: 100 }, { easing: easeOutElastic });
Разные функции формируют различную визуальную плотность движения:
При создании функций плавности учитываются следующие свойства:
Оптимальные функции:
Кастомные функции часто строятся на основе физических моделей или эмпирических кривых.
const softStep = (t) => t * t * (3 - 2 * t);
Поведение:
const smooth = (t) => t * t * (3 - 2 * t);
Используется для:
Motion One совместим с функциями, аналогичными CSS cubic-bezier, но расширяет модель до JS-функций.
Пример приближённой кривой CSS:
const cubicBezier = (p0, p1, p2, p3) => {
return (t) => {
const u = 1 - t;
return (
u * u * u * p0 +
3 * u * u * t * p1 +
3 * u * t * t * p2 +
t * t * t * p3
);
};
};
Такая реализация позволяет: