Затухание и инерция

В анимациях движение редко заканчивается мгновенно. Реалистичность достигается за счёт имитации физических процессов: трения, сопротивления среды и инерции. В библиотеке Popmotion эти эффекты реализуются через специализированные функции, позволяющие моделировать постепенное замедление и «докатывание» объектов.

Затухание (decay) и инерция (inertia) — два взаимосвязанных механизма, описывающих движение объекта после прекращения внешнего воздействия.


Затухание (Decay)

Основная идея

Затухание моделирует ситуацию, при которой объект продолжает движение с уменьшающейся скоростью под действием трения. Это типично для прокрутки, свайпов и жестов.

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

Базовый пример

import { decay } from "popmotion";

decay({
  velocity: 300, // начальная скорость
  from: 0        // начальная позиция
}).start(v => {
  console.log(v);
});

Ключевые параметры

  • velocity — начальная скорость движения
  • from — начальное значение
  • power — сила инерции (по умолчанию 0.8)
  • timeConstant — скорость затухания
  • restDelta — порог остановки

Принцип работы

Алгоритм основан на экспоненциальном убывании скорости:

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

Управление затуханием

Изменяя параметры, можно добиться разных эффектов:

decay({
  velocity: 500,
  power: 0.6,
  timeConstant: 200
}).start(v => {
  console.log(v);
});
  • большее power — более длинное движение
  • меньшее timeConstant — быстреее затухание

Ограничение движения

Часто требуется ограничить движение диапазоном значений. В этом случае используются параметры min и max.

decay({
  velocity: 400,
  from: 0,
  min: 0,
  max: 300
}).start(v => {
  console.log(v);
});

Если значение выходит за границы, Popmotion может автоматически применить эффект «отскока».


Отскок (Bounce)

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

  • bounceStiffness — жёсткость пружины
  • bounceDamping — демпфирование
decay({
  velocity: 600,
  from: 100,
  min: 0,
  max: 300,
  bounceStiffness: 200,
  bounceDamping: 20
}).start(v => {
  console.log(v);
});

Это создаёт ощущение физического взаимодействия с границами.


Инерция (Inertia)

Общая концепция

Инерция — более высокоуровневая абстракция, объединяющая:

  • начальную скорость
  • затухание
  • ограничения
  • отскок

В Popmotion инерция реализована через функцию inertia, которая автоматически выбирает подходящую модель движения.

Пример использования

import { inertia } from "popmotion";

inertia({
  velocity: 300,
  from: 0,
  min: 0,
  max: 500
}).start(v => {
  console.log(v);
});

Поведение

Функция inertia:

  1. Запускает движение с учётом начальной скорости
  2. Применяет затухание
  3. Проверяет границы
  4. При необходимости запускает пружинный возврат

Сравнение decay и inertia

Характеристика decay inertia
Уровень Низкоуровневый Высокоуровневый
Контроль Полный Частично автоматический
Ограничения Опционально Встроены
Отскок Настраивается Встроен

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

Затухание и инерция активно применяются в обработке жестов:

  • прокрутка списков
  • свайпы карточек
  • drag-and-drop интерфейсы

Пример интеграции с drag:

import { listen, inertia } from "popmotion";

let velocity = 0;

listen(document, "pointermove").start(e => {
  velocity = e.movementX;
});

listen(document, "pointerup").start(() => {
  inertia({
    velocity,
    from: 0
  }).start(v => {
    console.log(v);
  });
});

Комбинирование с другими анимациями

Popmotion позволяет комбинировать затухание с другими типами анимаций:

  • spring — для возврата в исходное положение
  • tween — для управляемых переходов
  • keyframes — для сложных последовательностей

Пример:

import { decay, spring } from "popmotion";

decay({
  velocity: 500,
  from: 0,
  min: 0,
  max: 300
}).start({
  update: v => console.log(v),
  complete: () => {
    spring({
      from: 300,
      to: 0
    }).start(v => console.log(v));
  }
});

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

Инерционная прокрутка

  • пользователь отпускает список
  • скорость сохраняется
  • список плавно замедляется

Свайп карточки

  • движение зависит от силы жеста
  • слабый свайп — возврат
  • сильный — уход за пределы экрана

Drag с ограничениями

  • объект перемещается свободно
  • при выходе за границы — мягкий возврат

Тонкая настройка поведения

Управление чувствительностью

  • увеличение velocity усиливает эффект
  • настройка power влияет на дальность

Реализм движения

  • сочетание decay + spring создаёт физически правдоподобное поведение
  • важно учитывать частоту кадров и производительность

Оптимизация

  • избегание лишних вычислений в update
  • использование requestAnimationFrame (встроено в Popmotion)

Особенности реализации

  • Popmotion использует функциональный подход
  • анимации являются потоками значений (streams)
  • управление происходит через методы start, stop, update

Каждое движение — это непрерывное вычисление значений, основанное на времени и параметрах физической модели.


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

Кастомные условия остановки

decay({
  velocity: 300,
  restDelta: 0.5
}).start(v => {
  console.log(v);
});

Позволяет контролировать точность завершения анимации.


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

Хотя Popmotion не требует ручного контроля времени, параметры позволяют косвенно влиять на длительность:

  • timeConstant
  • power

Использование с transform

import { decay, transform } from "popmotion";

const map = transform({
  from: [0, 300],
  to: [0, 1]
});

decay({
  velocity: 400
}).start(v => {
  console.log(map(v));
});

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


Поведение в интерфейсах

Затухание и инерция делают интерфейс:

  • отзывчивым
  • предсказуемым
  • физически правдоподобным

Неправильная настройка приводит к:

  • «резиновым» или неестественным движениям
  • слишком резким остановкам
  • потере контроля над анимацией

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