Easing-функции определяют характер изменения значения во времени. В отличие от линейной интерполяции, где скорость постоянна, easing позволяет задавать ускорение, замедление, колебания и другие нелинейные эффекты. Это критически важно для создания естественных и выразительных анимаций.
В библиотеке Popmotion easing-функции представляют собой обычные
функции, принимающие значение времени t в диапазоне от
0 до 1 и возвращающие преобразованное
значение, также в диапазоне 0–1.
const easing = (t) => t
Такой пример соответствует линейному движению.
Любая пользовательская easing-функция должна соответствовать следующим требованиям:
t находится в диапазоне
[0, 1][0, 1]Простейший пример — квадратичное ускорение:
const easeIn = (t) => t * t
Здесь движение начинается медленно и ускоряется к концу.
const easeInCubic = (t) => t * t * t
Чем выше степень, тем более выражено начальное замедление.
Для создания эффекта замедления используется обратная трансформация:
const easeOutCubic = (t) => 1 - Math.pow(1 - t, 3)
Анимация начинается быстро и плавно замедляется к завершению.
const easeInOutCubic = (t) => {
return t < 0.5
? 4 * t * t * t
: 1 - Math.pow(-2 * t + 2, 3) / 2
}
Первая половина — ускорение, вторая — замедление.
В Popmotion easing-функции передаются в конфигурацию анимации:
import { animate } from "popmotion"
animate({
from: 0,
to: 100,
duration: 1000,
ease: (t) => t * t,
onUpdate: (value) => console.log(value)
})
Функция ease будет применяться к каждому шагу
анимации.
const easeInExpo = (t) => {
return t === 0 ? 0 : Math.pow(2, 10 * (t - 1))
}
Резкое ускорение ближе к концу.
const easeInOutSine = (t) => {
return -(Math.cos(Math.PI * t) - 1) / 2
}
Очень плавное и естественное движение.
Иногда требуется управлять формой кривой через параметры:
const createPowerEasing = (power) => {
return (t) => Math.pow(t, power)
}
const easeInQuad = createPowerEasing(2)
const easeInQuart = createPowerEasing(4)
Такой подход позволяет гибко переиспользовать логику.
const springEasing = (t) => {
return 1 - Math.cos(t * Math.PI * 4) * Math.exp(-t * 6)
}
Характерные колебания с затуханием.
const bounce = (t) => {
if (t < 1 / 2.75) {
return 7.5625 * t * t
} else if (t < 2 / 2.75) {
t -= 1.5 / 2.75
return 7.5625 * t * t + 0.75
} else if (t < 2.5 / 2.75) {
t -= 2.25 / 2.75
return 7.5625 * t * t + 0.9375
} else {
t -= 2.625 / 2.75
return 7.5625 * t * t + 0.984375
}
}
Создаёт иллюзию падения с отскоками.
Можно объединять функции для создания сложных эффектов:
const combine = (easeIn, easeOut) => {
return (t) => {
return t < 0.5
? easeIn(t * 2) / 2
: 0.5 + easeOut((t - 0.5) * 2) / 2
}
}
Пример использования:
const customEase = combine(
(t) => t * t,
(t) => 1 - Math.pow(1 - t, 2)
)
[0,1] может привести к некорректной
анимацииПример неправильной функции:
const badEasing = (t) => Math.sin(t * 100)
Такая функция вызывает хаотичные скачки.
Для анализа easing-функций удобно строить графики:
const sample = (fn, steps = 100) => {
const values = []
for (let i = 0; i <= steps; i++) {
values.push(fn(i / steps))
}
return values
}
Полученные значения можно отобразить через canvas или графические библиотеки.
Popmotion позволяет комбинировать easing с интерполяцией:
import { interpolate } from "popmotion"
const mixer = interpolate(
[0, 1],
[0, 100],
{ ease: (t) => t * t }
)
console.log(mixer(0.5))
Easing применяется до интерполяции значений.
const customPiecewise = (t) => {
if (t < 0.3) return t * t
if (t < 0.7) return 0.3 + (t - 0.3)
return 0.7 + Math.pow(t - 0.7, 2)
}
Позволяют точно контролировать разные фазы анимации.
Иногда требуется “перевернуть” функцию:
const invert = (ease) => {
return (t) => 1 - ease(1 - t)
}
Грамотно подобранная easing-функция делает анимацию более естественной, улучшает восприятие интерфейса и повышает качество взаимодействия.