Относительные значения

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


Базовый принцип заключается в использовании строкового выражения с префиксом += или -=. Эти операторы интерпретируются как «добавить к текущему значению» или «вычесть из текущего значения».

Velocity(element, {
  left: "+=100px",
  opacity: "-=0.2"
}, 500);

В этом случае:

  • текущее значение left увеличивается на 100 пикселей
  • opacity уменьшается на 0.2

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


Числовые относительные изменения

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

Velocity(element, {
  width: "+=50",
  height: "-=20"
}, 400);

Если у свойства уже есть единицы измерения, библиотека сохраняет их и корректно применяет изменение. Это позволяет избегать ручного парсинга getComputedStyle.

Ключевые особенности:

  • если значение было в px, результат останется в px
  • если значение без единиц (например, opacity), вычисление идет как чистое число
  • строка обязательно должна содержать оператор += или -=

Работа с CSS единицами

Velocity.js корректно обрабатывает относительные значения с единицами измерения CSS. Это касается:

  • px
  • %
  • em
  • rem
  • vh / vw (в зависимости от свойства)

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

Velocity(element, {
  left: "+=10%",
  width: "-=5%"
}, 600);

Особенность заключается в том, что процентные значения интерпретируются относительно текущего контекста элемента, а не глобального состояния страницы. Это критично при работе с адаптивными интерфейсами.


Относительные изменения и transform

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

Velocity(element, {
  translateX: "+=200px",
  rotateZ: "+=45deg",
  scale: "*=1.1"
}, 700);

Здесь появляются дополнительные операторы:

  • += — добавление
  • -= — вычитание
  • *= — умножение (для scale и аналогичных параметров)

Особенно важно поведение scale:

Velocity(element, {
  scale: "*=1.2"
}, 300);

Это означает постепенное увеличение текущего масштаба на 20%, а не переход к фиксированному значению.


Последовательные относительные анимации

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

Velocity(element, {
  left: "+=100px"
}, 300);

Velocity(element, {
  left: "+=100px"
}, 300);

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


Комбинация с очередью анимаций

Velocity.js использует очередь анимаций, что делает относительные значения особенно удобными при построении сложных сценариев.

Velocity(element, { left: "+=100px" }, 300);
Velocity(element, { top: "+=50px" }, 300);
Velocity(element, { left: "-=30px" }, 300);

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


Взаимодействие с начальным состоянием

Относительные значения всегда опираются на текущее вычисленное состояние элемента в момент старта анимации.

Это означает:

  • если элемент изменён CSS-классом — используется новое значение
  • если изменён inline-стиль — он имеет приоритет
  • если значение не задано явно — используется вычисленный стиль браузера

Пример:

element.style.left = "200px";

Velocity(element, {
  left: "+=50px"
}, 300);

Результат будет 250px, а не 50px.


Ошибки и ограничения

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

  1. Нельзя использовать относительные операторы без числового значения ❌ "+=px""+=10px"

  2. Не все CSS свойства поддерживают числовую интерполяцию

  3. Сложные вычисляемые значения (например, calc()) могут вести себя непредсказуемо

  4. Относительные операции не работают с неконвертируемыми строками


Практические паттерны использования

Относительные значения особенно полезны в интерфейсных сценариях:

Движение по сетке

Velocity(element, {
  left: "+=120px",
  top: "+=80px"
}, 250);

Инкрементальное изменение состояния

Velocity(button, {
  scale: "*=0.95"
}, 100);

Плавное «раскачивание» интерфейса

Velocity(element, { rotateZ: "+=5deg" }, 100)
  .then(() => Velocity(element, { rotateZ: "-=10deg" }, 100))
  .then(() => Velocity(element, { rotateZ: "+=5deg" }, 100));

Стабильность состояния при повторных вызовах

Одной из особенностей Velocity.js является то, что относительные значения сохраняют консистентность даже при многократных вызовах подряд. Однако при параллельных анимациях на одном свойстве возможны конфликты, поскольку каждое новое значение пересчитывается относительно текущего состояния на момент старта конкретной анимации.

Это требует аккуратного проектирования логики:

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

Поведение при прерывании анимации

Если анимация прерывается, текущее вычисленное значение становится новой базой для следующего относительного изменения. Это позволяет создавать интерактивные эффекты, где пользовательское действие мгновенно становится частью анимационного состояния.

Velocity(element, "stop");

Velocity(element, {
  left: "+=30px"
}, 200);

Элемент продолжит движение от текущей позиции, а не от изначальной точки старта.