В Motion One координация нескольких элементов достигается через единый контекст времени, где анимации начинают, продолжаются и завершаются относительно общей системы отсчёта. Такой подход позволяет строить сложные сцены, в которых поведение элементов строго детерминировано и не зависит от ручного управления задержками.
Основой синхронизации выступает функция создания анимаций с единым таймингом и возможностью объединения в последовательности или параллельные группы.
import { animate } from "motion";
const box = document.querySelector(".box");
const title = document.querySelector(".title");
animate(box, { x: 200, opacity: 1 }, { duration: 1 });
animate(title, { y: -50, opacity: 1 }, { duration: 1 });
В приведённом примере оба элемента запускаются одновременно, но их синхронизация ограничена лишь стартовым моментом. Для более точного управления используется композиция через таймлайн.
Таймлайн позволяет объединять несколько анимаций в единую структуру времени, где каждая операция получает собственное смещение относительно общей шкалы.
import { timeline } from "motion";
timeline([
[".box", { x: 200 }, { duration: 0.6 }],
[".title", { opacity: 1 }, { duration: 0.4 }, "-=0.2"],
[".subtitle", { y: 30 }, { duration: 0.5 }, "+=0.1"]
]);
Каждый элемент таймлайна описывается массивом, где задаются:
Относительные смещения "-=0.2" и "+=0.1"
позволяют точно выстраивать пересечения и паузы между элементами,
формируя плотную синхронизацию.
Синхронизация часто требует разделения анимаций на блоки, которые либо идут строго последовательно, либо проигрываются одновременно.
timeline([
[".step-1", { opacity: 1 }, { duration: 0.4 }],
[".step-2", { opacity: 1 }, { duration: 0.4 }],
[".step-3", { opacity: 1 }, { duration: 0.4 }]
]);
Каждый следующий шаг начинается после завершения предыдущего, формируя линейную структуру.
timeline([
[".left", { x: 100 }, { duration: 0.8 }],
[".right", { x: -100 }, { duration: 0.8 }],
[".center", { scale: 1.2 }, { duration: 0.8 }]
]);
Если не задано смещение, все элементы стартуют одновременно, сохраняя общий временной контур.
Более сложные сценарии требуют частичного наложения анимаций. Motion One позволяет управлять этим через позиционные параметры в таймлайне.
timeline([
[".panel", { x: 300 }, { duration: 1 }],
[".overlay", { opacity: 1 }, { duration: 0.4 }, "-=0.7"],
[".content", { y: -20 }, { duration: 0.5 }, "-=0.3"]
]);
Перекрытия создают ощущение непрерывного движения, где элементы взаимодействуют во времени, а не существуют изолированно.
Stagger позволяет синхронизировать большое количество однотипных элементов с равномерным распределением задержек.
import { animate, stagger } from "motion";
animate(
".item",
{ opacity: 1, y: 0 },
{
delay: stagger(0.1),
duration: 0.5
}
);
Механизм stagger распределяет запуск анимаций по формуле последовательного смещения, сохраняя общую структуру группы.
Stagger может учитывать порядок элементов и их положение в DOM.
stagger(0.08, { start: 0.2 });
В результате элементы начинают анимацию не одновременно, но сохраняют единый ритм, что создаёт эффект волны.
Каждая анимация в Motion One возвращает управляющий объект, который позволяет координировать несколько процессов вручную.
const box = animate(".box", { x: 200 }, { duration: 1 });
const text = animate(".text", { opacity: 1 }, { duration: 1 });
box.pause();
text.pause();
setTimeout(() => {
box.play();
text.play();
}, 500);
Такой подход используется при необходимости внешнего контроля над временной логикой, например при взаимодействии с интерфейсом или состояниями приложения.
Координация анимаций может строиться на основе завершения предыдущих процессов.
animate(".box", { x: 200 }, { duration: 1 }).finished.then(() => {
animate(".text", { opacity: 1 }, { duration: 0.5 });
});
Механизм finished создаёт цепочку зависимостей, где
следующий элемент строго привязан к завершению предыдущего.
Motion One использует единый временной контекст, в котором можно задавать согласованные параметры для нескольких анимаций.
const options = {
duration: 0.8,
easing: "ease-in-out"
};
animate(".a", { x: 100 }, options);
animate(".b", { y: 100 }, options);
animate(".c", { scale: 1.2 }, options);
Общий объект параметров гарантирует идентичное поведение времени и кривых движения, что упрощает визуальную согласованность.
Синхронизация часто применяется для управления состояниями появления и исчезновения элементов. В таких сценариях важно согласовать вход и выход разных компонентов.
animate(".modal", { opacity: 1, scale: 1 }, { duration: 0.4 });
animate(".backdrop", { opacity: 1 }, { duration: 0.4 });
При закрытии порядок может быть инвертирован для сохранения логической целостности визуального перехода.
Для сложных интерфейсов используется абстракция, объединяющая несколько анимаций в единый блок.
function openMenu() {
return timeline([
[".menu", { x: 0 }, { duration: 0.5 }],
[".menu-item", { opacity: 1 }, { duration: 0.3 }, stagger(0.05)],
[".overlay", { opacity: 1 }, { duration: 0.4 }, "-=0.3"]
]);
}
Такая композиция позволяет повторно использовать синхронизированные сценарии без дублирования логики.
Синхронизация часто требуется при одновременном изменении свойств нескольких элементов, связанных общей визуальной логикой.
timeline([
[".image", { scale: 1.1 }, { duration: 0.6 }],
[".caption", { y: -10, opacity: 1 }, { duration: 0.6 }, "<"],
[".border", { scaleX: 1 }, { duration: 0.6 }, "<"]
]);
Символ < указывает на одновременный старт с
предыдущим элементом, обеспечивая строгую временную привязку.
При построении интерфейсных переходов с множеством элементов синхронизация становится центральным механизмом управления визуальной логикой. Каждое состояние интерфейса представляет собой набор согласованных анимаций, которые должны завершаться в строго определённые моменты.
timeline([
[".header", { y: 0 }, { duration: 0.4 }],
[".content", { opacity: 1 }, { duration: 0.6 }, "-=0.2"],
[".sidebar", { x: 0 }, { duration: 0.5 }, "-=0.4"],
[".footer", { opacity: 1 }, { duration: 0.3 }]
]);
В таких структурах важна не только последовательность, но и баланс перекрытий, создающий ощущение цельного движения интерфейса.
Единый ритм анимаций достигается через унификацию длительностей и easing-функций. Это создаёт ощущение, что элементы принадлежат одной системе движения.
const rhythm = {
duration: 0.7,
easing: "ease-out"
};
animate(".card", { y: 0 }, rhythm);
animate(".icon", { scale: 1 }, rhythm);
animate(".text", { opacity: 1 }, rhythm);
При таком подходе синхронизация достигается не только временными смещениями, но и общими динамическими характеристиками движения.