Пружинная физика

Пружинная физика в анимациях моделирует поведение реальных упругих систем, основанных на законе Гука. В библиотеке Popmotion она используется для создания естественных, плавных и «живых» переходов между значениями. В отличие от линейных или временных анимаций, пружинные движения зависят не только от времени, но и от физических параметров: массы, жесткости и демпфирования.

Ключевая идея — имитация силы, которая стремится вернуть объект к равновесию, с возможными колебаниями вокруг целевого значения.


Математическая модель

В основе лежит дифференциальное уравнение второго порядка:

  • Сила пружины: F = -k * x
  • Демпфирование: F_d = -c * v

Где:

  • k — коэффициент жесткости (stiffness)
  • x — отклонение от равновесия
  • c — коэффициент демпфирования (damping)
  • v — скорость
  • m — масса объекта

Полная формула движения:

m * a = -k * x - c * v

Popmotion решает это уравнение численно, обновляя состояние на каждом кадре.


Параметры пружины в Popmotion

stiffness (жесткость)

Определяет, насколько сильно пружина стремится вернуть объект к цели.

  • Большое значение → быстрый возврат, резкое движение
  • Малое значение → мягкое, растянутое движение
spring({ from: 0, to: 100, stiffness: 200 })

damping (демпфирование)

Контролирует затухание колебаний.

  • Низкое значение → выраженные колебания (bounce)
  • Высокое значение → быстрое затухание
spring({ from: 0, to: 100, damping: 10 })

mass (масса)

Влияет на инерцию системы.

  • Большая масса → медленное ускорение и замедление
  • Малая масса → более отзывчивое движение
spring({ from: 0, to: 100, mass: 2 })

Базовое использование

import { spring } from "popmotion";

spring({
  from: 0,
  to: 300
}).start(v => {
  console.log(v);
});

Анимация автоматически рассчитывает промежуточные значения и завершает работу, когда система стабилизируется.


Поведение при разных настройках

1. Критическое демпфирование

Система возвращается к цели максимально быстро без колебаний.

spring({
  from: 0,
  to: 100,
  stiffness: 100,
  damping: 20
});

2. Недодемпфированная система (с колебаниями)

spring({
  from: 0,
  to: 100,
  stiffness: 150,
  damping: 5
});

Результат — эффект “перелета” и возврата.

3. Перегруженная система (overdamped)

spring({
  from: 0,
  to: 100,
  stiffness: 50,
  damping: 50
});

Движение медленное и без колебаний.


Начальная скорость

Пружина может стартовать с заданной скоростью:

spring({
  from: 0,
  to: 100,
  velocity: 200
});

Это важно при работе с жестами (drag, swipe), когда объект уже движется в момент начала анимации.


Rest-параметры

Popmotion завершает анимацию, когда движение становится незаметным.

  • restSpeed — минимальная скорость
  • restDelta — минимальное расстояние до цели
spring({
  from: 0,
  to: 100,
  restSpeed: 0.01,
  restDelta: 0.01
});

Это предотвращает бесконечные микроколебания.


Векторные значения

Пружины работают не только с числами, но и с массивами или объектами:

spring({
  from: { x: 0, y: 0 },
  to: { x: 100, y: 200 }
}).start(v => {
  console.log(v.x, v.y);
});

Каждое значение анимируется независимо, но с общей физической моделью.


Работа с DOM

import { styler } from "popmotion";

const div = document.querySelector("div");
const divStyler = styler(div);

spring({
  from: 0,
  to: 300
}).start(v => {
  divStyler.set("x", v);
});

Использование styler обеспечивает эффективное обновление свойств.


Связка с пользовательским вводом

Пружины часто применяются после взаимодействий:

import { listen, pointer, spring } from "popmotion";

listen(document, "mousedown").start(() => {
  pointer().start(pos => {
    // перемещение элемента
  });
});

После отпускания:

spring({
  from: currentPosition,
  to: 0,
  velocity: currentVelocity
});

Так достигается естественное «возвращение» элемента.


Сравнение с tween

Свойство spring tween
Основа физика время
Контроль параметры системы duration, easing
Поведение динамическое предсказуемое
Реализм высокий средний

Пружины лучше подходят для UI, где важна отзывчивость и натуральность.


Комбинирование с другими операторами

chain

import { chain, spring, tween } from "popmotion";

chain(
  tween({ to: 100, duration: 300 }),
  spring({ to: 0 })
).start(console.log);

parallel

import { parallel, spring } from "popmotion";

parallel(
  spring({ from: 0, to: 100 }),
  spring({ from: 50, to: 200 })
).start(console.log);

Ограничение значений

import { clamp } from "popmotion";

spring({
  from: 0,
  to: 500
})
.pipe(clamp(0, 300))
.start(console.log);

Позволяет ограничить диапазон движения.


Производительность

Пружинные анимации в Popmotion оптимизированы:

  • используют requestAnimationFrame
  • минимизируют перерасчёты
  • работают с батчингом обновлений

Рекомендуется:

  • избегать лишних подписок
  • использовать styler
  • не создавать новые анимации в каждом кадре

Практические сценарии

Возврат элемента после drag

spring({
  from: draggedX,
  to: 0,
  velocity: dragVelocity
});

Анимация кнопки при клике

spring({
  from: 1,
  to: 1.2,
  stiffness: 300,
  damping: 10
});

Появление элемента

spring({
  from: 0,
  to: 1,
  stiffness: 120,
  damping: 15
});

Тонкая настройка ощущений

Небольшие изменения параметров радикально меняют восприятие:

  • увеличение stiffness делает интерфейс «резким»
  • уменьшение damping добавляет игривость
  • увеличение mass создаёт ощущение тяжести

Эти параметры позволяют передавать «характер» интерфейса.


Численная интеграция

Popmotion использует пошаговую интеграцию:

  1. вычисляется ускорение
  2. обновляется скорость
  3. обновляется позиция

Это происходит на каждом кадре (~60 раз в секунду), что создаёт плавную анимацию.


Ограничения модели

  • не учитывает нелинейные силы
  • не моделирует сложные системы (например, цепочки пружин)
  • точность зависит от частоты кадров

Тем не менее, для UI-задач модель оптимальна по балансу производительности и реализма.


Рекомендации по настройке

  • Для интерфейсов: stiffness: 100–300, damping: 10–30
  • Для bounce-эффектов: damping < 10
  • Для «тяжёлых» объектов: mass > 1.5
  • Для быстрых реакций: увеличивать stiffness, снижать mass

Взаимодействие с easing

В отличие от tween, пружины не используют easing-функции. Их поведение формируется исключительно физическими параметрами. Это делает анимацию менее предсказуемой, но более естественной.


Отладка и визуализация

Для анализа поведения удобно:

  • логировать значения
  • отображать графики позиции и скорости
  • экспериментировать с параметрами в реальном времени

Расширенные возможности

Управление в реальном времени

const animation = spring({ from: 0, to: 100 }).start(v => {
  console.log(v);
});

// остановка
animation.stop();

Перезапуск

animation.stop();

spring({ from: current, to: newTarget }).start();

Итоговое понимание

Пружинная физика в Popmotion — это инструмент для создания динамичных, адаптивных анимаций, реагирующих на контекст и взаимодействие. Управление через физические параметры позволяет добиваться высокой выразительности интерфейса без сложных математических вычислений вручную.