Пружинная анимация в Popmotion строится на классической модели гармонического осциллятора. Движение объекта определяется взаимодействием трёх ключевых факторов:
Эта модель позволяет создавать естественные, «живые» анимации, в которых движение не является линейным, а подчиняется законам физики.
Поведение пружины описывается дифференциальным уравнением второго порядка:
m + c + kx = 0
где:
В контексте анимации это означает, что позиция объекта зависит не только от времени, но и от его текущей скорости и ускорения.
В Popmotion управление пружиной осуществляется через набор параметров:
Определяет силу, с которой пружина стремится вернуть объект к целевому значению.
import { spring } from "popmotion";
spring({
from: 0,
to: 100,
stiffness: 200
}).start(v => console.log(v));
Контролирует затухание колебаний.
spring({
from: 0,
to: 100,
damping: 5
}).start(v => console.log(v));
Влияет на инерцию системы.
spring({
from: 0,
to: 100,
mass: 2
}).start(v => console.log(v));
В зависимости от соотношения параметров система может находиться в разных режимах:
spring({
from: 0,
to: 100,
stiffness: 150,
damping: 10
})
spring({
stiffness: 200,
damping: 20
})
spring({
stiffness: 100,
damping: 50
})
Параметр velocity задаёт начальную скорость объекта. Это
особенно важно при прерывании анимаций или взаимодействии с жестами.
spring({
from: 0,
to: 100,
velocity: 300
})
Высокая начальная скорость может привести к:
Popmotion завершает анимацию, когда выполняются два условия:
restSpeed)restDelta)spring({
to: 100,
restSpeed: 0.01,
restDelta: 0.01
})
Это предотвращает бесконечные микроколебания.
Пружина может анимировать не только числа:
"100px")"50%")spring({
from: "0px",
to: "200px"
}).start(v => {
element.style.transform = `translateX(${v})`;
});
Пружины можно комбинировать с другими анимациями:
import { chain, tween } from "popmotion";
chain(
tween({ to: 100 }),
spring({ to: 0 })
).start(console.log);
import { parallel, spring } from "popmotion";
parallel(
spring({ to: 100 }),
spring({ to: 200 })
).start(v => console.log(v));
spring({
from: 1,
to: 1.2,
stiffness: 300,
damping: 10
})
Используется для масштабирования (scale) при
нажатии.
spring({
from: dragPosition,
to: 0,
velocity: dragVelocity
})
Создаёт ощущение физического возврата элемента.
spring({
from: 0,
to: 100,
stiffness: 250,
damping: 8
})
Объект слегка «перелетает» цель и возвращается обратно.
Параметры не работают изолированно:
Баланс параметров — ключ к реалистичной анимации.
requestAnimationFrame внутри Popmotion
обеспечивает плавностьrestDelta снижает
нагрузку| Характеристика | Spring | Tween |
|---|---|---|
| Поведение | Физическое | Линейное/кривые |
| Реакция на ввод | Высокая | Ограниченная |
| Реализм | Высокий | Средний |
| Контроль | Через физику | Через easing |
Пружины лучше подходят для:
Popmotion интегрирует численное решение дифференциального уравнения с использованием пошаговой интеграции:
Этот цикл выполняется на каждом кадре:
velocity += acceleration * deltaTime;
position += velocity * deltaTime;
Такой подход обеспечивает:
Popmotion автоматически учитывает:
Это делает анимации консистентными даже при просадках производительности.
Вместо привычных параметров можно использовать:
stiffnessdampingmassили более абстрактные:
durationbouncePopmotion может автоматически преобразовывать одни параметры в другие.
Пружина может использоваться как источник значений:
spring({ to: 100 }).start(v => {
customRender(v);
});
Это позволяет интегрировать её в любые рендер-системы.
Типичные проблемы:
restDeltadampingstiffnessКорректировка параметров решает большинство из них.
Их комбинация формирует характер движения — от мягкого и плавного до резкого и пружинистого.