Функция интерполяции в Popmotion используется для преобразования значения из одного числового диапазона в другой с возможностью нелинейного распределения, ограничения выходных значений и применения различных стратегий поведения за пределами диапазона.
Механизм interpolate является базовым строительным
блоком для анимаций, так как позволяет связывать прогресс анимации
(обычно от 0 до 1) с любыми прикладными значениями: координатами,
углами, прозрачностью, цветами и сложными шкалами.
Интерполяция — это отображение входного диапазона на выходной:
0 → 1)0 → 100)Линейное преобразование можно выразить как:
output = (input - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin
В Popmotion эта логика инкапсулирована и расширена дополнительными возможностями.
import { interpolate } from '@popmotion/popcorn';
const mapper = interpolate([0, 1], [0, 100]);
mapper(0); // 0
mapper(0.5); // 50
mapper(1); // 100
Первый массив задаёт входной диапазон, второй — выходной.
Интерполяция чаще всего применяется вместе с прогрессом анимации:
import { animate, interpolate } from 'popmotion';
const scaleMap = interpolate([0, 1], [0.5, 1.5]);
animate({
from: 0,
to: 1,
duration: 1000,
onUpdate: (v) => {
const scale = scaleMap(v);
element.style.transform = `scale(${scale})`;
}
});
Здесь интерполяция отделяет вычисление значения от механики анимации.
Интерполяция поддерживает разбиение на несколько контрольных точек.
const colorMap = interpolate(
[0, 0.5, 1],
['#ff0000', '#00ff00', '#0000ff']
);
Такое поведение создаёт плавный переход через промежуточные значения.
Помимо линейного соответствия, можно задавать кривые сглаживания через easing.
import { easeInOut } from '@popmotion/easing';
const smoothMap = interpolate(
[0, 1],
[0, 100],
{ ease: easeInOut }
);
Easing изменяет распределение значений внутри диапазона, не меняя конечные точки.
Одной из ключевых особенностей является поведение при выходе входного значения за пределы диапазона.
const mapper = interpolate([0, 1], [0, 100], {
clamp: false
});
mapper(-0.5); // -50
mapper(1.5); // 150
Если включить ограничение:
const mapper = interpolate([0, 1], [0, 100], {
clamp: true
});
mapper(-0.5); // 0
mapper(1.5); // 100
Clamp используется в UI-анимациях для предотвращения «вылета» значений.
Интерполяция часто применяется для визуальных эффектов.
const opacityMap = interpolate([0, 1], [0, 1]);
const yMap = interpolate([0, 1], [50, 0]);
onUpdate(v => {
element.style.opacity = opacityMap(v);
element.style.transform = `translateY(${yMap(v)}px)`;
});
const rotateMap = interpolate([0, 1], [0, 360]);
const scaleMap = interpolate([0, 1], [1, 2]);
element.style.transform = `
rotate(${rotateMap(progress)}deg)
scale(${scaleMap(progress)})
`;
Для работы с цветами используется преобразование между цветовыми пространствами.
const colorMap = interpolate(
[0, 1],
['rgb(255, 0, 0)', 'rgb(0, 0, 255)']
);
element.style.background = colorMap(progress);
Внутренне Popmotion преобразует цвета в числовые каналы и интерполирует каждый компонент отдельно.
При сложных анимациях удобно использовать несколько сегментов:
const map = interpolate(
[0, 0.3, 0.6, 1],
[0, 100, 50, 200]
);
Такой подход позволяет моделировать:
Интерполяция часто применяется для преобразования жестов в UI изменения.
const dragToScale = interpolate(
[0, 300],
[1, 1.8],
{ clamp: true }
);
pointerTracker(({ x }) => {
element.style.transform = `scale(${dragToScale(x)})`;
});
Иногда требуется обратный маппинг — восстановление исходного диапазона.
const inverse = interpolate([0, 100], [0, 1]);
inverse(50); // 0.5
Это используется при синхронизации состояния интерфейса с анимацией.
Интерполяции можно вкладывать друг в друга для создания сложных систем преобразований.
const progressMap = interpolate([0, 1], [0, 100]);
const opacityMap = interpolate([0, 100], [1, 0]);
const opacity = opacityMap(progressMap(t));
Такой подход позволяет строить цепочки трансформаций без усложнения основной логики.
Неправильное выравнивание диапазонов:
interpolate([0, 100], [0, 1])(0.5); // ошибка логики ожидания
Использование без нормализации входных данных приводит к непредсказуемым результатам.
Создание интерполятора — операция, которую выгодно выполнять один раз:
const map = interpolate([0, 1], [0, 100]);
// повторное использование
map(0.1);
map(0.2);
Создание функции внутри каждого кадра анимации увеличивает нагрузку на GC и снижает плавность UI.
Интерполяция выступает промежуточным слоем между:
Она отделяет математическое преобразование от логики управления состоянием, позволяя строить предсказуемые анимационные системы без привязки к конкретной платформе рендеринга.