Property maps

Двухточечное описание значений через карту свойств

В основе системы анимации mo.js лежит принцип декларативного описания изменений свойств во времени. Одним из ключевых механизмов выступает property map — способ задания изменения значения свойства через отображение прогресса анимации в конкретное значение.

Формально любое анимируемое свойство может быть задано не только фиксированным числом, но и структурой, описывающей поведение во времени:

  • начальное значение
  • конечное значение
  • промежуточная логика вычисления

Базовая форма выглядит как отображение от 0 до 1:

x: {
  0: 0,
  1: 100
}

Здесь:

  • 0 — стартовое состояние анимации
  • 1 — завершение
  • значения — результат интерполяции

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


Интерполяция как основа property mapping

Любая property map в mo.js опирается на интерполяцию значений. При изменении времени анимации движок вычисляет текущий прогресс p ∈ [0, 1] и преобразует его в значение свойства.

Линейный случай:

opacity: {
  0: 0,
  1: 1
}

Эквивалентен функции:

opacity: (p) => p

Таким образом, property map можно рассматривать как декларативную форму записи функции от прогресса.


Функциональные property maps

Помимо объектной формы, mo.js допускает использование функций, полностью заменяющих карту значений. Это расширяет модель до произвольных преобразований:

x: (p) => 100 * Math.sin(p * Math.PI)

Здесь:

  • p — нормализованный прогресс анимации
  • возвращаемое значение — вычисленное состояние свойства

Функциональный вариант позволяет:

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

Сегментированные карты значений

Property map может содержать более двух контрольных точек. Это позволяет строить кусочно-линейные функции:

x: {
  0: 0,
  0.3: 50,
  0.7: -20,
  1: 100
}

Такая структура интерпретируется как последовательность сегментов:

  • 0 → 0.3: рост до 50
  • 0.3 → 0.7: падение до -20
  • 0.7 → 1: рост до 100

Механизм внутри движка:

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

Применение easing внутри property maps

Easing-функции могут комбинироваться с property maps, изменяя характер интерполяции между точками.

x: {
  0: 0,
  1: 200,
  easing: 'ease.out.quad'
}

или через явное применение:

x: {
  0: 0,
  1: 200
},
easing: 'ease.in.out.cubic'

Easing влияет на распределение прогресса p, но не на сами значения карты. Это создаёт двухуровневую модель:

  • property map задаёт пространство значений
  • easing задаёт кривую времени

Композиция property maps в сложных объектах

В mo.js анимации часто включают сразу несколько свойств, каждое из которых может быть представлено собственной картой:

const circle = new mojs.Shape({
  left: 0,
  top: 0,
  radius: {
    0: 10,
    1: 50
  },
  x: {
    0: 0,
    1: 300
  },
  opacity: {
    0: 1,
    1: 0
  }
});

Каждое свойство:

  • имеет независимую карту
  • синхронизировано общим временем анимации
  • интерпретируется через единый прогресс p

Математическая модель property mapping

Поведение property map можно формализовать как функцию:

[ f(p) = v_i + (v_{i+1} - v_i)]

где:

    1. — текущий прогресс
  • (p_i, p_{i+1}) — соседние ключи карты
  • (v_i, v_{i+1}) — соответствующие значения

Для функционального варианта:

[ f(p) = g(p)]

где (g) — произвольная пользовательская функция.


Использование property maps для сложных трансформаций

Property maps часто применяются для создания непрямолинейных анимаций:

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

Пример комбинированной трансформации:

scale: {
  0: 0.5,
  0.5: 1.5,
  1: 1
},
angle: (p) => 360 * p

Здесь:

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

Вложенные зависимости и вычисляемые карты

В расширенных сценариях property map может зависеть от внешних параметров:

const intensity = 2;

x: (p) => 100 * Math.pow(p, intensity)

Подобная конструкция создаёт:

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

Сравнение объектной и функциональной формы

Объектная форма:

y: {
  0: 0,
  1: 200
}

Характеристики:

  • простота
  • декларативность
  • ограниченность линейной моделью

Функциональная форма:

y: (p) => 200 * Math.sin(p * Math.PI)

Характеристики:

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

Поведение при синхронизации нескольких property maps

При одновременной анимации нескольких свойств mo.js использует единый временной контур. Это означает:

  • все property maps получают одинаковый p
  • вычисления выполняются в одном цикле обновления
  • результат формирует кадр состояния объекта

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


Ограничения модели property maps

Несмотря на гибкость, модель имеет структурные особенности:

  • нормализация прогресса всегда в диапазоне [0, 1]
  • ключи объектной карты должны быть упорядочиваемыми значениями
  • вычисления происходят на каждом кадре, что влияет на производительность при сложных функциях
  • отсутствует автоматическая оптимизация кэширования пользовательских функций

Детерминированность вычислений

Property maps в mo.js вычисляются детерминированно: при одинаковых входных параметрах результат всегда идентичен.

Это свойство критично для:

  • синхронизации анимаций
  • воспроизводимости эффектов
  • композиции нескольких timeline-объектов

Любая случайность должна быть явно зафиксирована в функции:

x: (p) => 100 * Math.random() * p

что приводит к недетерминированному поведению при каждом кадре.