Инерция и физика жестов

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

Природа инерционного движения

Инерционное движение описывается тремя основными характеристиками:

  • Начальная скорость (velocity) — скорость объекта в момент завершения взаимодействия
  • Сопротивление (friction) — сила, замедляющая движение
  • Границы (bounds) — ограничения, в пределах которых может перемещаться объект

В Motion One инерция реализуется через функцию animate с использованием параметра type: "inertia".

Базовая инерция

Простейшая форма инерции:

import { animate } from "motion";

animate(element, { x: 500 }, {
  type: "inertia",
  velocity: 1000
});

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

  • velocity — определяет начальный импульс
  • power — влияет на дистанцию, которую пройдет элемент
  • timeConstant — регулирует скорость затухания

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

Затухание движения моделируется экспоненциальной функцией. Чем выше значение timeConstant, тем дольше сохраняется движение:

animate(element, { x: 500 }, {
  type: "inertia",
  velocity: 800,
  timeConstant: 300
});
  • Малые значения (100–200) создают резкую остановку
  • Большие значения (400+) дают эффект “скольжения”

Ограничение движения (границы)

Часто требуется ограничить перемещение элемента. Motion One поддерживает это через min и max:

animate(element, { x: 1000 }, {
  type: "inertia",
  velocity: 1200,
  min: 0,
  max: 800
});

При достижении границы возможны два сценария:

  • остановка
  • отскок (если задана упругость)

Эффект отскока (bounce)

Для создания более реалистичной физики добавляется параметр bounce:

animate(element, { x: 1000 }, {
  type: "inertia",
  velocity: 1500,
  min: 0,
  max: 800,
  bounce: 0.5
});
  • 0 — без отскока
  • 1 — максимальная упругость

Дополнительно:

  • bounceStiffness — жесткость отскока
  • bounceDamping — затухание колебаний

Связь с жестами

Инерция особенно важна при работе с drag-жестами. Motion One позволяет отслеживать скорость перемещения и использовать её для продолжения движения.

Пример с использованием Pointer Events:

let velocity = 0;
let lastX = 0;
let lastTime = 0;

element.addEventListener("pointermove", (event) => {
  const now = performance.now();
  const delta = event.clientX - lastX;
  const time = now - lastTime;

  velocity = delta / time * 1000;

  lastX = event.clientX;
  lastTime = now;
});

element.addEventListener("pointerup", () => {
  animate(element, { x: "+=0" }, {
    type: "inertia",
    velocity
  });
});

Здесь:

  • скорость вычисляется вручную
  • затем передаётся в инерционную анимацию

Сопротивление и “масса”

Хотя Motion One не использует напрямую понятие массы, её можно имитировать через комбинацию параметров:

  • высокая масса → большая timeConstant
  • лёгкий объект → меньшее затухание
animate(element, { x: 500 }, {
  type: "inertia",
  velocity: 1000,
  timeConstant: 600
});

Комбинация с пружинной физикой

Часто инерция сочетается с пружиной при достижении границ:

animate(element, { x: 1000 }, {
  type: "inertia",
  velocity: 1200,
  min: 0,
  max: 800,
  bounce: 0.6,
  bounceStiffness: 300,
  bounceDamping: 20
});

Так создаётся поведение:

  1. свободное движение
  2. столкновение с границей
  3. пружинный отскок

Реализация “карточек” и свайпов

Инерция активно применяется в интерфейсах свайпа:

element.addEventListener("pointerup", () => {
  if (velocity > 500) {
    animate(element, { x: 1000 }, {
      type: "inertia",
      velocity
    });
  } else {
    animate(element, { x: 0 }, {
      type: "spring"
    });
  }
});

Логика:

  • высокая скорость → элемент “улетает”
  • низкая → возвращается

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

Инерция учитывает знак скорости:

  • положительная скорость → движение вправо
  • отрицательная → влево
animate(element, { x: 0 }, {
  type: "inertia",
  velocity: -800
});

Прерывание инерции

Анимация может быть остановлена:

const controls = animate(element, { x: 500 }, {
  type: "inertia",
  velocity: 1000
});

controls.stop();

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

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

Сбалансированная инерция:

  • velocity: 500–1500
  • timeConstant: 200–400

Для мобильных интерфейсов:

  • более высокая инерция
  • плавное затухание

Для desktop:

  • меньшее скольжение
  • более быстрые остановки

Оптимизация восприятия

Инерция должна:

  • соответствовать ожиданиям пользователя
  • не быть слишком “тяжёлой”
  • не создавать ощущение потери контроля

Чрезмерная инерция ухудшает UX, особенно в интерфейсах с точным позиционированием.

Синхронизация с другими свойствами

Инерцию можно применять не только к x и y, но и к другим параметрам:

animate(element, { rotate: 360 }, {
  type: "inertia",
  velocity: 200
});

Однако визуально правдоподобной остаётся только трансляция и прокрутка.

Внутренняя модель движения

Motion One использует экспоненциальное затухание:

  • скорость уменьшается со временем
  • позиция интегрируется из скорости

Это даёт:

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

Типичные ошибки

  • слишком высокая velocity → элемент “вылетает” за пределы
  • отсутствие границ → неконтролируемое движение
  • чрезмерный bounce → неестественная физика
  • игнорирование пользовательского ввода во время анимации

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

Инерционный скроллинг:

animate(container, { scrollTop: 1000 }, {
  type: "inertia",
  velocity: 2000
});

Карусели:

  • инерция определяет количество пролистываемых элементов
  • добавляется “snap” после остановки

Игровые интерфейсы:

  • имитация броска
  • движение объектов с затуханием

Итоговое поведение системы

Комбинация параметров формирует характер движения:

Параметр Эффект
velocity начальный импульс
timeConstant длительность движения
power дальность
bounce упругость
min/max границы

Грамотная настройка этих параметров позволяет создавать интерфейсы, максимально приближенные к физическому взаимодействию, что делает пользовательский опыт более естественным и интуитивным.