Любая анимация сводится к отображению одного диапазона значений в
другой. В простейшем виде это функция, которая принимает прогресс
t в диапазоне от 0 до 1 и
возвращает вычисленное значение свойства: позицию, прозрачность,
масштаб, цвет.
Формально это записывается как:
t ∈ [0, 1]yТакое отображение лежит в основе всех механизмов интерполяции в Motion One: keyframes, easing, физические модели и пользовательские трансформации.
В Motion One ключевым способом задания динамики является возможность использовать функции вместо статических значений.
Анимация перестает быть фиксированным набором точек и превращается в вычисляемую зависимость:
import { animate } from "motion";
animate(element, {
x: (latest) => latest * 200,
opacity: (latest) => 1 - latest
});
Здесь latest — нормализованный прогресс, который Motion
One передает в функцию. Каждое обновление кадра вычисляет новое
значение.
Такой подход позволяет:
Одним из центральных инструментов является функция преобразования диапазонов. Она реализует классическое отображение:
[ f(x) : [a, b] ]
В Motion One это выражается через transform:
import { transform } from "motion";
const map = transform([0, 1], [0, 100]);
map(0.5); // 50
Функция вычисляет относительное положение входного значения в диапазоне:
[ t = ]
И применяет его к выходному диапазону:
[ y = c + t(d - c)]
Любая анимация в Motion One приводит данные к нормализованной форме.
Даже сложные сценарии — скролл, жесты, физика — сводятся к значению
progress.
Пример преобразования scroll в диапазон:
const opacity = transform([0, 300], [1, 0]);
window.addEventListener("scroll", () => {
const value = opacity(window.scrollY);
element.style.opacity = value;
});
Здесь происходит двойное отображение:
Mapping-функции в Motion One можно комбинировать, формируя цепочки преобразований.
Пример композиции:
import { transform } from "motion";
const scaleMap = transform([0, 1], [1, 1.5]);
const easeMap = (t) => t * t;
const result = (t) => scaleMap(easeMap(t));
Здесь происходит последовательное преобразование:
Такой подход позволяет собирать сложные анимации из простых функций.
Keyframes в Motion One можно рассматривать как дискретную форму mapping-функции.
animate(element, {
x: [0, 100, 50, 200]
});
Внутри происходит:
Фактически создается кусочно-заданная функция:
[ f(t) = f_1(t) f_2(t) f_3(t)]
Помимо линейного отображения используются нелинейные функции, которые изменяют характер движения.
const easeIn = (t) => t * t;
const easeOut = (t) => 1 - Math.pow(1 - t, 2);
Такие функции изменяют распределение скорости:
const wave = (t) => Math.sin(t * Math.PI * 2);
Используются для:
Цветовые значения также могут быть результатом отображения.
import { transform } from "motion";
const colorMap = transform(
[0, 1],
["#ff0000", "#00ff00"]
);
Внутри Motion One происходит интерполяция каналов RGB:
Mapping может быть привязан к системному времени, а не к прогрессу анимации.
const rotate = (t) => t * 360;
animate(element, {
rotate: (latest) => rotate(latest)
});
При этом latest фактически отражает текущий тик
анимационного цикла.
Входные события мыши или касания также приводятся к нормализованным значениям.
const mapX = transform([0, window.innerWidth], [-1, 1]);
window.addEventListener("pointermove", (e) => {
const normalized = mapX(e.clientX);
element.style.transform = `translateX(${normalized * 100}px)`;
});
Такое преобразование используется для:
Motion One поддерживает использование функций как вычисляемых значений свойств.
animate(element, {
x: (progress, element) => progress * 300 + element.offsetLeft
});
Здесь mapping получает доступ к:
Это позволяет строить зависимые анимации, где итоговое значение учитывает контекст.
Физические модели (spring, inertia) также можно рассматривать как mapping-функции времени.
[ f(t) = (t, x_0, x_1)]
В этом случае отображение становится неявным:
Иногда требуется комбинировать разные диапазоны:
const map = (t) => {
if (t < 0.5) return t * 2;
return 1 - (t - 0.5) * 2;
};
Такие функции создают:
Все описанные механизмы сводятся к единому принципу:
В рамках Motion One mapping-функции выступают универсальным уровнем абстракции между данными и визуальным состоянием, позволяя строить анимации как чистые математические зависимости без жесткой привязки к ключевым кадрам или фиксированным значениям