Физическая модель пружин

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

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


Базовое уравнение движения

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

[ m x’’ + c x’ + k x = 0]

где:

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

Это уравнение отражает баланс сил:

  • сила упругости стремится вернуть объект в исходное положение
  • демпфирование гасит колебания
  • масса влияет на инерцию движения

Основные параметры в Motion One

Motion One предоставляет упрощённый интерфейс для работы с этой моделью, скрывая сложную математику за набором параметров.

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

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

  • Высокие значения → быстрый возврат, резкие движения
  • Низкие значения → медленные, мягкие анимации
animate(element, { x: 100 }, {
  type: "spring",
  stiffness: 300
});

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

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

  • Низкое значение → сильные колебания (bounce)
  • Высокое значение → быстрое затухание
animate(element, { x: 100 }, {
  type: "spring",
  damping: 10
});

mass (масса)

Влияет на инерцию объекта.

  • Большая масса → медленное реагирование
  • Маленькая масса → быстрые изменения
animate(element, { x: 100 }, {
  type: "spring",
  mass: 2
});

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

Недостаточное демпфирование (Underdamped)

  • Низкий damping
  • Объект многократно пересекает конечную точку
  • Создаёт эффект «пружинистости»
animate(element, { x: 100 }, {
  type: "spring",
  stiffness: 200,
  damping: 5
});

Критическое демпфирование (Critically damped)

  • Оптимальное значение damping
  • Объект достигает цели максимально быстро без колебаний
animate(element, { x: 100 }, {
  type: "spring",
  stiffness: 200,
  damping: 20
});

Переизбыточное демпфирование (Overdamped)

  • Очень высокий damping
  • Медленное движение без колебаний
animate(element, { x: 100 }, {
  type: "spring",
  stiffness: 200,
  damping: 50
});

Внутренний механизм Motion One

Motion One использует численное интегрирование для вычисления положения объекта на каждом кадре. Вместо фиксированной длительности анимации, система:

  1. Вычисляет ускорение на основе текущего состояния
  2. Обновляет скорость
  3. Обновляет позицию
  4. Повторяет цикл до достижения устойчивого состояния

Анимация завершается, когда:

  • скорость близка к нулю
  • отклонение от цели минимально

Параметры restSpeed и restDelta

Для определения момента остановки используются дополнительные параметры:

restSpeed

Минимальная скорость, при которой движение считается завершённым.

animate(element, { x: 100 }, {
  type: "spring",
  restSpeed: 0.01
});

restDelta

Минимальное расстояние до цели.

animate(element, { x: 100 }, {
  type: "spring",
  restDelta: 0.01
});

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

Пружина может учитывать начальную скорость, что важно при интерактивных сценариях.

animate(element, { x: 100 }, {
  type: "spring",
  velocity: 5
});

Это позволяет:

  • продолжать движение после drag
  • создавать инерционные эффекты
  • делать переходы более реалистичными

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

Пружинная модель особенно эффективна при:

Drag & Drop

После отпускания элемент «возвращается» с учетом скорости:

animate(element, { x: 0 }, {
  type: "spring",
  velocity: currentVelocity
});

Hover-эффекты

Создание мягкой реакции интерфейса:

animate(button, { scale: 1.1 }, {
  type: "spring",
  stiffness: 400,
  damping: 15
});

Переключение состояний

Плавные переходы между UI-состояниями:

animate(panel, { opacity: 1, y: 0 }, {
  type: "spring",
  stiffness: 150,
  damping: 20
});

Сравнение с временными анимациями

Характеристика Пружина Временная анимация
Основа Физика Время
Контроль Через параметры Через duration/easing
Поведение Нелинейное Предсказуемое
Реализм Высокий Ограниченный

Практические рекомендации

Быстрые UI-реакции

  • stiffness: высокий (300–500)
  • damping: средний (20–30)

Мягкие анимации

  • stiffness: низкий (50–150)
  • damping: средний

Эффект «резины»

  • stiffness: средний
  • damping: низкий (5–10)

Комбинирование параметров

Параметры взаимосвязаны:

  • увеличение stiffness требует увеличения damping
  • увеличение mass замедляет всю систему
  • слишком низкий damping делает анимацию хаотичной

Пример сбалансированной конфигурации:

animate(element, { x: 100 }, {
  type: "spring",
  stiffness: 250,
  damping: 25,
  mass: 1
});

Влияние частоты кадров

Пружинная модель чувствительна к частоте обновления (обычно 60 FPS). Motion One компенсирует это, используя delta-time между кадрами, что обеспечивает стабильность анимации даже при просадках производительности.


Расширенные сценарии

Каскадные анимации

Несколько элементов могут использовать одинаковые параметры, создавая согласованное движение:

items.forEach((item, i) => {
  animate(item, { y: 0 }, {
    delay: i * 0.05,
    type: "spring"
  });
});

Связанные пружины

Можно имитировать цепочки объектов, где один влияет на другой через общие параметры или состояние.


Динамическое изменение параметров

Параметры могут адаптироваться во время выполнения:

const stiffness = isActive ? 300 : 100;

animate(element, { scale: 1.2 }, {
  type: "spring",
  stiffness
});

Ошибки и антипаттерны

  • Слишком высокий stiffness без увеличения damping → «дёргание»
  • Низкий damping → бесконечные колебания
  • Игнорирование mass → нереалистичные ощущения
  • Использование spring там, где нужна точная синхронизация по времени

Оптимизация

  • Использование transform вместо layout-свойств
  • Минимизация количества одновременно анимируемых элементов
  • Повторное использование конфигураций
const springConfig = {
  type: "spring",
  stiffness: 200,
  damping: 20
};

animate(el1, { x: 100 }, springConfig);
animate(el2, { y: 50 }, springConfig);

Итоговая модель восприятия

Пружинная анимация в Motion One — это не просто эффект, а симуляция физического поведения, где:

  • движение определяется силами, а не временем
  • параметры влияют на характер, а не длительность
  • результат ощущается естественным благодаря имитации реального мира