Анимационные пресеты в Motion One представляют собой способ стандартизации и переиспользования конфигураций анимации, позволяя формировать единый слой абстракции над низкоуровневыми параметрами: длительностью, easing-функциями, трансформациями, ключевыми кадрами и поведением на старте и завершении анимации.
Базовый пресет в Motion One фактически является объектом, который
повторяет сигнатуру функции animate. В него включаются
параметры:
durationdelayeasingfilldirectioniterationskeyframestransformopacityПресет формируется как неизменяемая конфигурация, которая затем передаётся в разные анимационные вызовы без модификации исходного объекта.
Основной принцип заключается в разделении описания анимации и её применения к конкретным DOM-узлам.
Простейший вариант пресета представляет собой объект-конфигурацию:
const fadeInPreset = {
keyframes: {
opacity: [0, 1],
transform: ["translateY(10px)", "translateY(0px)"]
},
duration: 0.4,
easing: "ease-out"
};
Такая структура позволяет использовать один и тот же шаблон для множества элементов без повторного описания логики анимации.
При увеличении количества вариаций статические объекты становятся недостаточными. Применяется подход фабрик пресетов, где параметры параметризуются:
const createFadePreset = (distance = 10, duration = 0.4) => ({
keyframes: {
opacity: [0, 1],
transform: [`translateY(${distance}px)`, "translateY(0px)"]
},
duration,
easing: "ease-out"
});
Фабричный подход позволяет:
Сложные интерфейсы требуют объединения нескольких анимационных слоёв. Пресеты начинают рассматриваться как композиционные единицы.
const basePreset = {
duration: 0.3,
easing: "ease-out"
};
const fadePreset = {
keyframes: { opacity: [0, 1] }
};
const slidePreset = {
keyframes: { transform: ["translateY(20px)", "translateY(0px)"] }
};
const composedPreset = {
...basePreset,
keyframes: {
...fadePreset.keyframes,
...slidePreset.keyframes
}
};
При композиции ключевым становится управление конфликтами свойств.
Например, transform не может быть безопасно слит через
spread-оператор без потери значений, поэтому применяется либо строковая
конкатенация трансформаций, либо специализированная функция сборки
трансформаций.
Transform является наиболее чувствительной частью анимации, поскольку включает несколько независимых подпространств:
Корректная стратегия заключается в разбиении transform на атомарные значения:
const transformPreset = {
translateY: [20, 0],
scale: [0.95, 1]
};
Далее система сборки пресета преобразует их в единый transform:
const buildTransform = (t) =>
`translateY(${t.translateY}px) scale(${t.scale})`;
Такой подход устраняет проблему перезаписи transform и делает пресеты совместимыми между собой.
При масштабировании интерфейса возникает необходимость централизованного хранилища пресетов.
const presets = {
fadeIn: {
keyframes: { opacity: [0, 1] },
duration: 0.25,
easing: "ease-out"
},
fadeOut: {
keyframes: { opacity: [1, 0] },
duration: 0.2,
easing: "ease-in"
},
pop: {
keyframes: {
transform: ["scale(0.9)", "scale(1)"]
},
duration: 0.3,
easing: "spring(1, 80, 10, 0)"
}
};
Такая структура позволяет использовать строковые идентификаторы вместо конфигураций:
animate(element, presets.fadeIn);
При этом логика остаётся централизованной, а визуальный язык интерфейса становится консистентным.
Часто требуется учитывать состояние UI: hover, active, disabled, loading. Пресеты начинают выступать как описание состояний.
const buttonPresets = {
idle: {
scale: 1,
duration: 0.2
},
hover: {
scale: 1.05,
duration: 0.15
},
active: {
scale: 0.98,
duration: 0.1
}
};
Слой интерпретации преобразует состояния в анимации:
const applyState = (el, state) => {
animate(el, {
transform: `scale(${buttonPresets[state].scale})`,
duration: buttonPresets[state].duration
});
};
Easing-функции в Motion One могут быть как строковыми, так и кастомными кривыми. Пресеты часто включают стандартизированные кривые:
const easingPresets = {
smooth: "ease-in-out",
enter: "ease-out",
exit: "ease-in",
bounce: "spring(1, 100, 10, 0)"
};
Использование именованных easing-пресетов обеспечивает визуальную согласованность всей системы анимаций.
При росте системы пресеты разделяются на уровни:
Базовый слой определяет физику движения, семантический — тип анимации, компонентный — конкретное поведение UI-элемента, контекстный — глобальные переходы.
const primitives = {
fast: { duration: 0.15 },
normal: { duration: 0.3 },
slow: { duration: 0.6 }
};
const semantic = {
fadeIn: {
...primitives.normal,
keyframes: { opacity: [0, 1] }
}
};
const component = {
modalEnter: {
...semantic.fadeIn,
keyframes: {
opacity: [0, 1],
transform: ["scale(0.9)", "scale(1)"]
}
}
};
Такой подход снижает энтропию анимационной системы и упрощает её расширение.
Motion One предоставляет функцию animate, которая
становится базовым исполнителем пресетов. Пресеты не заменяют её, а
расширяют:
const runPreset = (el, preset) => animate(el, preset);
runPreset(box, presets.fadeIn);
Дополнительный уровень абстракции позволяет внедрять:
При работе с массивами элементов пресеты становятся основой stagger-анимаций:
const listPreset = {
keyframes: {
opacity: [0, 1],
transform: ["translateY(15px)", "translateY(0px)"]
},
delay: (i) => i * 0.05,
duration: 0.3
};
Функциональный delay позволяет формировать каскадные
эффекты без дополнительного кода управления циклами.
В сложных интерфейсах пресеты комбинируются с временными шкалами. Каждый пресет становится сегментом общей анимационной композиции:
timeline([
[elementA, presets.fadeIn],
[elementB, presets.slide],
[elementC, presets.pop]
]);
Такой подход превращает набор независимых конфигураций в синхронизированную систему движения.
Механизм расширения позволяет создавать вариации без копирования:
const fadeInSlow = {
...presets.fadeIn,
duration: 0.8
};
или через функцию:
const extendPreset = (base, overrides) => ({
...base,
...overrides
});
Это поддерживает принцип неизменяемости базовых конфигураций.
В TypeScript пресеты становятся строго типизированными объектами, что снижает количество ошибок при масштабировании:
type AnimationPreset = {
keyframes: Record<string, string[] | number[]>;
duration?: number;
easing?: string;
delay?: number | ((i: number) => number);
};
Типизация обеспечивает контроль над структурой пресетов и предотвращает некорректные конфигурации на этапе разработки.
При большом количестве пресетов возникает нагрузка на систему рендеринга. Оптимизация включает:
Особенно критичным становится избегание пересоздания объектов на каждый рендер, поскольку это влияет на garbage collection и производительность анимационного цикла.
Система пресетов постепенно превращается в декларативный язык описания движения интерфейса. Вместо отдельных вызовов анимации формируется словарь поведения, где каждый ключ описывает конкретный визуальный паттерн:
Такой подход делает Motion One не просто инструментом анимации, а системой описания динамики интерфейса через повторяемые структурированные паттерны.