Velocity.Hook

Velocity.Hook — механизм доступа к отдельным компонентам сложных CSS-свойств без необходимости вручную разбирать и пересобирать строки значений. Позволяет работать с под-свойствами (sub-properties), такими как отдельные значения transform, box-shadow, clip, backgroundPosition и других составных свойств.

В стандартном CSS изменение, например, одного компонента transform требует переписывания всей строки:

transform: translateX(10px) scale(1.2) rotate(45deg);

Любое изменение translateX требует заново указать scale и rotate. Velocity.Hook устраняет это ограничение.


Общий принцип работы

Velocity хранит сложные свойства в разобранном виде и предоставляет доступ к их частям через синтаксис:

Velocity.hook(element, "propertyName.subProperty")

Где:

  • propertyName — CSS-свойство (например, transform)
  • subProperty — его компонент (например, translateX)

Чтение значений через Hook

Для получения текущего значения под-свойства используется следующий синтаксис:

var value = Velocity.hook(element, "transform.translateX");

Пример:

var x = Velocity.hook(element, "transform.translateX");
console.log(x); // "10px"

Если значение не было задано ранее, Velocity возвращает значение по умолчанию.


Установка значений через Hook

Изменение отдельного компонента выполняется аналогично:

Velocity.hook(element, "transform.translateX", "50px");

После выполнения Velocity автоматически пересобирает итоговое свойство:

transform: translateX(50px) scale(1.2) rotate(45deg);

Остальные компоненты остаются неизменными.


Поддерживаемые составные свойства

1. Transform

Наиболее часто используемая группа. Поддерживаются:

  • translateX
  • translateY
  • translateZ
  • scale
  • scaleX
  • scaleY
  • rotate
  • rotateX
  • rotateY
  • skewX
  • skewY

Пример:

Velocity.hook(element, "transform.scale", 1.5);
Velocity.hook(element, "transform.rotate", "90deg");

2. Background Position

CSS-свойство background-position содержит два значения:

  • backgroundPositionX
  • backgroundPositionY

Пример:

Velocity.hook(element, "backgroundPositionX", "50%");
Velocity.hook(element, "backgroundPositionY", "20%");

3. Box Shadow

Свойство box-shadow включает несколько параметров:

  • boxShadowX
  • boxShadowY
  • boxShadowBlur
  • boxShadowSpread
  • boxShadowColor

Пример:

Velocity.hook(element, "boxShadowBlur", "10px");
Velocity.hook(element, "boxShadowColor", "rgba(0,0,0,0.5)");

4. Clip

Свойство clip (устаревающее, но поддерживаемое):

  • clipTop
  • clipRight
  • clipBottom
  • clipLeft

Пример:

Velocity.hook(element, "clipTop", "10px");

Использование вместе с анимацией

Hooks можно использовать внутри Velocity анимаций:

Velocity(element, {
    "transform.translateX": "100px",
    "transform.rotate": "180deg"
}, {
    duration: 1000
});

Velocity автоматически применяет изменения через hooks без ручной сборки строки transform.


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

Velocity хранит значения сложных свойств в кэше (data store), что позволяет:

  • избегать повторного чтения из DOM
  • ускорять анимации
  • поддерживать консистентность значений

При использовании hook:

  1. Проверяется наличие закэшированного значения
  2. При отсутствии — вычисляется текущее значение через getComputedStyle
  3. Значение разбивается на компоненты
  4. Обновляется только нужная часть
  5. Пересобирается итоговая строка свойства

Значения по умолчанию

Если компонент не был явно задан, Velocity использует дефолтные значения:

Для transform:

  • translateX, translateY: 0px
  • scale: 1
  • rotate: 0deg

Это позволяет безопасно изменять только нужные параметры:

Velocity.hook(element, "transform.scale", 2);

Даже если transform ранее не был задан.


Особенности работы с единицами измерения

Velocity автоматически добавляет единицы измерения при необходимости:

Velocity.hook(element, "transform.translateX", 50);

Результат:

translateX(50px)

Однако для углов и процентов лучше указывать явно:

Velocity.hook(element, "transform.rotate", "45deg");
Velocity.hook(element, "backgroundPositionX", "50%");

Работа с цветами

Некоторые hooks поддерживают цветовые значения:

Velocity.hook(element, "boxShadowColor", "#ff0000");

Velocity нормализует цвет в формат rgba.


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

Использование hooks предпочтительнее, чем ручное управление строками CSS:

Преимущества:

  • минимизация перерасчётов
  • отсутствие парсинга строк вручную
  • снижение количества ошибок
  • эффективный reflow/repaint

Ограничения

  • Работает только с поддерживаемыми составными свойствами
  • Нельзя создавать произвольные hooks без расширения Velocity
  • Некоторые CSS-свойства (например, filter) имеют ограниченную поддержку

Расширение hooks

Velocity позволяет добавлять собственные hooks через внутренние API (не документировано официально):

Velocity.CSS.Hooks.register("myProperty", "mySubProperty");

Используется редко и требует понимания внутренней архитектуры.


Типичные сценарии применения

Анимация transform без перезаписи

Velocity(element, {
    "transform.translateY": "200px"
});

Без потери текущих scale и rotate.


Плавное изменение тени

Velocity(element, {
    boxShadowBlur: "20px"
});

Параллакс-эффекты

window.addEventListener("scroll", function() {
    var offset = window.scrollY;
    Velocity.hook(element, "transform.translateY", offset * 0.5 + "px");
});

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

Без hooks:

element.style.transform = "translateX(50px) scale(1.2)";

С hooks:

Velocity.hook(element, "transform.translateX", "50px");

Разница:

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

Взаимодействие с CSS и inline-стилями

Velocity всегда работает с inline-стилями, но учитывает значения из:

  • CSS-файлов
  • computed styles
  • предыдущих анимаций

Hooks обеспечивают единый интерфейс доступа ко всем этим источникам.


Ошибки и отладка

Типичные проблемы:

1. Неверное имя hook:

Velocity.hook(element, "transform.translatex", "50px"); // ошибка

Регистр имеет значение.

2. Отсутствие единиц:

Velocity.hook(element, "transform.rotate", 45); // может работать некорректно

3. Несовместимые значения:

Velocity.hook(element, "boxShadowColor", "invalid");

Поведение при сбросе значений

Чтобы удалить значение:

Velocity.hook(element, "transform.translateX", null);

Velocity вернёт компонент к значению по умолчанию.


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

Hooks полностью совместимы с параметрами анимации:

Velocity(element, {
    "transform.scale": 2
}, {
    duration: 500,
    easing: "easeInOutQuad",
    queue: false
});

Практическая ценность

Velocity.Hook превращает работу со сложными CSS-свойствами из строковой манипуляции в структурированную модель, приближенную к объектному доступу. Это особенно важно при построении сложных интерфейсов с большим количеством независимых анимационных параметров.