В основе системы анимации mo.js лежит принцип декларативного описания изменений свойств во времени. Одним из ключевых механизмов выступает property map — способ задания изменения значения свойства через отображение прогресса анимации в конкретное значение.
Формально любое анимируемое свойство может быть задано не только фиксированным числом, но и структурой, описывающей поведение во времени:
Базовая форма выглядит как отображение от 0 до 1:
x: {
0: 0,
1: 100
}
Здесь:
0 — стартовое состояние анимации1 — завершениеПодобная конструкция воспринимается как карта соответствий, где ключи определяют нормализованный прогресс анимации.
Любая property map в mo.js опирается на интерполяцию значений. При
изменении времени анимации движок вычисляет текущий прогресс
p ∈ [0, 1] и преобразует его в значение свойства.
Линейный случай:
opacity: {
0: 0,
1: 1
}
Эквивалентен функции:
opacity: (p) => p
Таким образом, property map можно рассматривать как декларативную форму записи функции от прогресса.
Помимо объектной формы, mo.js допускает использование функций, полностью заменяющих карту значений. Это расширяет модель до произвольных преобразований:
x: (p) => 100 * Math.sin(p * Math.PI)
Здесь:
p — нормализованный прогресс анимацииФункциональный вариант позволяет:
Property map может содержать более двух контрольных точек. Это позволяет строить кусочно-линейные функции:
x: {
0: 0,
0.3: 50,
0.7: -20,
1: 100
}
Такая структура интерпретируется как последовательность сегментов:
Механизм внутри движка:
Easing-функции могут комбинироваться с property maps, изменяя характер интерполяции между точками.
x: {
0: 0,
1: 200,
easing: 'ease.out.quad'
}
или через явное применение:
x: {
0: 0,
1: 200
},
easing: 'ease.in.out.cubic'
Easing влияет на распределение прогресса p, но не на
сами значения карты. Это создаёт двухуровневую модель:
В 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 map можно формализовать как функцию:
[ f(p) = v_i + (v_{i+1} - v_i)]
где:
Для функционального варианта:
[ f(p) = g(p)]
где (g) — произвольная пользовательская функция.
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)
Характеристики:
При одновременной анимации нескольких свойств mo.js использует единый временной контур. Это означает:
pЭто обеспечивает когерентность анимации даже при сложных комбинациях трансформаций.
Несмотря на гибкость, модель имеет структурные особенности:
Property maps в mo.js вычисляются детерминированно: при одинаковых входных параметрах результат всегда идентичен.
Это свойство критично для:
Любая случайность должна быть явно зафиксирована в функции:
x: (p) => 100 * Math.random() * p
что приводит к недетерминированному поведению при каждом кадре.