Работа с последовательным появлением элементов в Motion One строится вокруг идеи контролируемого тайминга: каждый следующий элемент начинает анимацию не одновременно с предыдущим, а с заданной задержкой, формируя визуальный каскад.
Последовательное появление элементов достигается через управление
задержками (delay) и координатой времени старта для каждого
анимируемого узла. В Motion One каждая анимация может быть запущена как
независимая единица, но синхронизирована с общей временной логикой.
Ключевая идея:
delayimport { animate } from "motion";
const items = document.querySelectorAll(".item");
items.forEach((item, index) => {
animate(
item,
{
opacity: [0, 1],
transform: ["translateY(20px)", "translateY(0px)"]
},
{
duration: 0.5,
delay: index * 0.1
}
);
});
Такой подход формирует линейную последовательность появления, где каждый следующий элемент отстает от предыдущего на фиксированный интервал.
В Motion One задержка не обязана быть линейной. Последовательность может строиться на произвольной функции времени:
items.forEach((item, index) => {
const delay = Math.pow(index, 1.2) * 0.08;
animate(
item,
{
opacity: [0, 1],
transform: ["scale(0.9)", "scale(1)"]
},
{
duration: 0.4,
delay
}
);
});
Такой подход позволяет избегать механической равномерности и формировать более органичную динамику появления.
Последовательность может быть построена не только через
delay, но и через управление прогрессом общей анимации. В
Motion One это достигается за счёт синхронизации нескольких элементов с
общей временной осью.
import { timeline } from "motion";
timeline([
[".item-1", { opacity: [0, 1], y: [20, 0] }, { duration: 0.4 }],
[".item-2", { opacity: [0, 1], y: [20, 0] }, { at: "+0.1", duration: 0.4 }],
[".item-3", { opacity: [0, 1], y: [20, 0] }, { at: "+0.1", duration: 0.4 }]
]);
Здесь параметр at задаёт относительное смещение во
времени относительно предыдущего ключевого кадра, формируя строго
контролируемую последовательность.
Когда требуется масштабируемая система анимаций, последовательность описывается как структура данных. В Motion One это позволяет отделить логику от DOM-манипуляций.
const sequence = [
{ selector: ".item-1", delay: 0 },
{ selector: ".item-2", delay: 0.1 },
{ selector: ".item-3", delay: 0.2 }
];
sequence.forEach(({ selector, delay }) => {
animate(
selector,
{
opacity: [0, 1],
transform: ["translateY(15px)", "translateY(0px)"]
},
{
duration: 0.45,
delay
}
);
});
Такой подход упрощает масштабирование при большом количестве элементов и делает последовательность управляемой через данные.
Последовательное появление часто применяется при динамической генерации элементов. В Motion One важно учитывать момент появления узлов в DOM, чтобы анимация запускалась только после их рендеринга.
function animateList(container) {
const items = container.querySelectorAll(".item");
items.forEach((item, index) => {
animate(
item,
{
opacity: [0, 1],
transform: ["translateY(10px)", "translateY(0)"]
},
{
duration: 0.3,
delay: index * 0.08
}
);
});
}
const observer = new MutationObserver((mutations) => {
mutations.forEach(() => {
const container = document.querySelector(".list");
if (container) animateList(container);
});
});
observer.observe(document.body, { childList: true, subtree: true });
Такой механизм позволяет связывать последовательность появления с жизненным циклом интерфейса.
В сложных интерфейсах важна не только последовательность, но и ритм.
В Motion One ритм формируется через комбинацию duration и
delay.
Основные паттерны:
items.forEach((item, index) => {
const groupSize = 4;
const groupIndex = Math.floor(index / groupSize);
const withinGroupIndex = index % groupSize;
animate(
item,
{
opacity: [0, 1],
transform: ["translateY(25px)", "translateY(0px)"]
},
{
duration: 0.35,
delay: groupIndex * 0.2 + withinGroupIndex * 0.08
}
);
});
Так формируется структурированное появление блоками, а не линейной цепочкой.
Иногда требуется инвертированная последовательность, где элементы появляются с конца массива. В Motion One это достигается изменением индекса:
items.forEach((item, index) => {
const reversedIndex = items.length - 1 - index;
animate(
item,
{
opacity: [0, 1],
transform: ["scale(0.8)", "scale(1)"]
},
{
duration: 0.4,
delay: reversedIndex * 0.1
}
);
});
Такой подход применяется в интерфейсах, где визуальный фокус должен начинаться с конца списка или последнего добавленного элемента.
В Motion One последовательное появление часто комбинируется с изменением состояния элементов: hover, active, loaded.
items.forEach((item, index) => {
animate(
item,
{
opacity: [0, 1],
transform: ["translateY(30px)", "translateY(0px)"]
},
{
duration: 0.5,
delay: index * 0.07
}
);
item.addEventListener("mouseenter", () => {
animate(item, { scale: 1.05 }, { duration: 0.2 });
});
item.addEventListener("mouseleave", () => {
animate(item, { scale: 1 }, { duration: 0.2 });
});
});
Последовательное появление формирует первичное восприятие интерфейса, а дальнейшие состояния поддерживают интерактивность без разрушения общей динамики.