Popmotion построена вокруг идеи управления изменением значений во времени через чистые функции. В основе лежит модель, где анимация рассматривается как поток данных: входное значение преобразуется в прогресс, затем через интерполяцию и временные функции превращается в итоговое состояние.
Любая анимация в Popmotion сводится к отображению времени в нормализованный диапазон:
01Этот диапазон называется прогрессом (progress). Временные функции отвечают за преобразование реального времени (миллисекунды) в значение прогресса.
Базовая модель:
time → progress (0 → 1) → transformation → output value
Ключевой момент — отделение времени от результата. Это позволяет применять единый механизм к разным типам анимаций: tween, spring, decay.
Tween — базовый механизм временного интерполирования значений между начальной и конечной точкой за заданную длительность.
Внутри tween происходит:
Простейшая форма линейного tween:
import { tween } from 'popmotion';
tween({
from: 0,
to: 100,
duration: 1000
}).start(v => {
console.log(v);
});
Фактически каждое значение v — результат функции:
v = from + (to - from) * progress
Интерполяция — процесс преобразования нормализованного прогресса в конкретное значение.
В Popmotion используется универсальная функция интерполяции:
Базовая линейная интерполяция:
lerp(a, b, t) = a + (b - a) * t
где:
a — начальное значениеb — конечное значениеt — прогресс (0–1)Popmotion предоставляет инструмент для создания собственных интерполяций:
import { interpolate } from 'popmotion';
const mixer = interpolate([0, 50, 100]);
mixer(0); // 0
mixer(0.5); // 50
mixer(1); // 100
Здесь интерполяция разбивает диапазон на сегменты. Если вход выходит за пределы, применяется ограничение или extrapolation.
Временные функции почти всегда требуют ограничения входных значений. Clamp обеспечивает фиксацию диапазона:
clamp(min, max, value)
Применение:
import { clamp } from 'popmotion';
const safe = clamp(0, 1, 1.5); // 1
Clamp используется перед интерполяцией, чтобы прогресс не выходил за пределы.
Easing-функции изменяют характер распределения прогресса во времени. Вместо линейного роста используется нелинейное преобразование.
Типичная форма:
easedProgress = easing(t)
Примеры поведения:
Пример:
import { tween, easing } from 'popmotion';
tween({
from: 0,
to: 100,
duration: 1000,
ease: easing.easeInOut
}).start(v => {
console.log(v);
});
Временные функции Popmotion опираются на
requestAnimationFrame. Это обеспечивает:
Алгоритм обновления:
фиксируется стартовое время
при каждом кадре вычисляется delta
вычисляется прогресс:
progress = (now - start) / durationприменяется easing
выполняется интерполяция
Важный принцип Popmotion — разделение временной логики и логики значения.
import { tween, interpolate, easing } from 'popmotion';
const mixer = interpolate([0, 100, 200]);
tween({
duration: 1000,
ease: easing.easeOut
}).start(v => {
const result = mixer(v / 100);
});
Здесь:
Перед интерполяцией время всегда приводится к диапазону 0–1:
t = (currentTime - startTime) / duration
Далее:
t = clamp(0, 1, t)
t = easing(t)
После этого значение передается в интерполяцию.
Внутренне Popmotion использует цепочку преобразований:
time → clamp → easing → interpolate → output
Эта модель позволяет строить сложные анимации из простых функций.
Pipe объединяет несколько функций в последовательный поток обработки значений:
import { pipe, clamp } from 'popmotion';
const process = pipe(
clamp(0, 1),
t => t * 2,
t => t - 1
);
В контексте временных функций pipe часто используется для:
Интерполяция не ограничивается числами. Popmotion поддерживает сложные типы данных:
rgb(0,0,0) → rgb(255,255,255)
Алгоритм:
{ x: 0, y: 0 } → { x: 100, y: 200 }
Применяется рекурсивная интерполяция свойств.
Keyframes позволяют задавать промежуточные точки:
0 → 50 → 20 → 100
Интерполяция разбивается на сегменты:
Каждый сегмент имеет свою локальную интерполяцию.
Decay — особый тип временной функции, где значение не привязано к конечной точке, а уменьшается по экспоненте.
Модель:
velocity → friction → gradual stop
Интерполяция здесь основана не на позиции, а на скорости изменения.
Временные функции Popmotion могут моделировать физику:
Интерполяция в этом контексте становится функцией состояния системы:
state(t) = physicsEquation(t)
Одной из сильных сторон Popmotion является возможность комбинировать временные функции:
Пример цепочки:
spring → clamp → interpolate → render
Архитектурно Popmotion строится на принципе:
Это позволяет:
Большинство выразительных анимаций достигается не изменением значений, а изменением функции времени.
Например:
Интерполяция остается неизменной, меняется только входной параметр времени.