CSS единицы и проценты

Popmotion обрабатывает анимации как последовательность числовых преобразований, где ключевая задача — корректно интерполировать значения между начальным и конечным состоянием. При работе с CSS это усложняется тем, что свойства могут иметь разные единицы измерения: пиксели, проценты, градусы, относительные величины и комбинированные форматы.

В основе механизма лежит разделение значения на числовую и строковую части. Это позволяет библиотеке понимать структуру "100px", "50%", "rotate(180deg)" и строить корректные переходы между ними.


Разбор CSS-значений на компоненты

Любое CSS-значение в Popmotion интерпретируется как составное выражение:

  • числовая часть
  • единица измерения
  • контекстная функция (например, translateX, rotate, scale)
  • строковые сегменты

Пример:

100px → { value: 100, unit: "px" }
50%   → { value: 50, unit: "%" }

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


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

Когда стартовое и конечное значение используют одинаковую единицу измерения, применяется числовая интерполяция:

100px → 300px

Фактически рассчитывается линейная функция:

value = start + (end - start) * progress

где progress изменяется от 0 до 1.

Такой подход обеспечивает стабильную анимацию без потери точности и без перерасчёта контекста DOM.


Работа с различными единицами измерения

Сложности возникают при смешении единиц:

100px → 50%

В этом случае Popmotion не может выполнить прямое числовое преобразование, так как проценты зависят от контекста (ширины или высоты родительского элемента).

Применяется один из подходов:

  • строковая интерполяция
  • вычисление через DOM-значения
  • использование функции-адаптера

Строковая интерполяция даёт промежуточные состояния вроде:

calc(100px + 25%)

Если поддерживается вычисление контекста, процент переводится в пиксели:

50% от 800px = 400px

Проценты и контекст вычисления

Процентные значения в CSS не являются абсолютными. Они зависят от свойства:

  • width → от ширины родителя
  • height → от высоты родителя
  • transform → от собственной геометрии элемента

Popmotion при работе с процентами опирается на текущие вычисленные стили DOM:

const parentWidth = element.parentNode.offsetWidth;
const target = parentWidth * 0.5;

Это позволяет превратить процентное значение в абсолютное число перед интерполяцией.


Особенности трансформаций и единиц

Свойства transform представляют отдельную категорию, так как содержат:

  • translateX(px, %)
  • translateY(px, %)
  • rotate(deg)
  • scale(unitless)

Popmotion разбивает трансформацию на компоненты и интерполирует каждую отдельно.

Пример:

translateX(0px) → translateX(100px)
rotate(0deg) → rotate(180deg)

Для каждого параметра используется своя шкала:

  • пиксели — линейная интерполяция
  • градусы — циклическая интерполяция
  • масштаб — безразмерное число

Обработка градусов и углов

Градусы требуют особого подхода из-за цикличности:

350deg → 10deg

Прямая интерполяция дала бы некорректный путь через 180°, поэтому Popmotion выбирает кратчайший путь:

  • либо по часовой стрелке
  • либо против неё

Это снижает визуальную нагрузку и делает анимации предсказуемыми.


Строковая интерполяция CSS

Если значения невозможно привести к числам, применяется строковая модель.

Пример:

"translateX(10px) scale(1)" → "translateX(200px) scale(2)"

Алгоритм:

  1. Разделение строки на числовые сегменты
  2. Интерполяция каждого числа
  3. Сборка итоговой строки

Такая модель используется как fallback для сложных CSS-значений.


Автоматическое определение типа значения

Popmotion анализирует входные данные и классифицирует их:

  • число без единиц → чистая интерполяция
  • число с единицей → unit interpolation
  • цвет → цветовая интерполяция (RGB/HSL)
  • строка → string interpolation

CSS-единицы рассматриваются как часть токена, а не как часть строки.


Влияние layout и reflow на проценты

Проценты зависят от состояния DOM в момент вычисления. Это означает:

  • изменение размера родителя изменяет результат анимации
  • ресайз окна влияет на конечные значения
  • flex/grid-контейнеры добавляют динамический контекст

Popmotion не фиксирует процентные значения автоматически, если не используется явное измерение перед стартом анимации.


Смешанные единицы в keyframes

При использовании ключевых кадров возможны комбинации:

0%   → 0px
50%  → 50%
100% → 200px

В таком случае Popmotion строит промежуточные значения через нормализацию:

  1. перевод всех значений в базовую систему
  2. интерполяция
  3. обратное преобразование при необходимости

Если нормализация невозможна, применяется строковая модель.


Оптимизация вычислений CSS-единиц

Для повышения производительности используются следующие подходы:

  • кэширование DOM-измерений
  • предварительное вычисление процентов
  • минимизация вызовов getComputedStyle
  • повторное использование интерполяционных функций

Особенно важно избегать повторного измерения layout внутри анимационного цикла.


Поведение при отсутствии единиц

Числа без единиц считаются универсальными значениями:

opacity: 0 → 1
scale: 1 → 2
zIndex: 0 → 10

Такие значения не требуют контекстной привязки и всегда интерполируются напрямую.


Практика смешивания px, %, deg и unitless значений

При комбинировании разных типов значений Popmotion выбирает стратегию по приоритету:

  1. числовые значения
  2. единичные значения с совместимыми единицами
  3. трансформации
  4. строковые fallback-значения

Это позволяет сохранить визуальную непрерывность даже при сложных стилевых переходах.


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

Некоторые комбинации CSS не имеют однозначного математического соответствия:

  • auto → 100px
  • min-content → 50%
  • fit-content → fixed value

В таких случаях Popmotion не выполняет числовую интерполяцию и переключается на дискретное или строковое изменение.


Итоговая модель обработки единиц

Внутренний пайплайн обработки CSS-значений можно описать как последовательность:

  1. парсинг значения
  2. определение типа
  3. выбор стратегии интерполяции
  4. нормализация (при возможности)
  5. вычисление промежуточных значений
  6. сборка итогового CSS-выражения