Настройка задержек для групп элементов

В Motion One групповая анимация строится вокруг идеи распределённого старта анимаций между элементами коллекции. Вместо синхронного запуска применяется смещение времени начала, формирующее каскадный эффект.

Ключевая характеристика такого подхода — управление не отдельным элементом, а набором элементов как единым контекстом, где каждый следующий участник получает индивидуальную задержку относительно базового времени старта.

Механизм stagger как основа распределённых задержек

Основной инструмент для создания последовательных задержек — функция stagger.

Она формирует зависимость задержки от позиции элемента в коллекции:

import { animate, stagger } from "motion";

animate(
  ".item",
  { opacity: [0, 1], transform: ["translateY(20px)", "translateY(0px)"] },
  { delay: stagger(0.1) }
);

В этом примере каждый следующий элемент получает дополнительную задержку 0.1 секунды относительно предыдущего.

Математически поведение можно представить как:

[ delay_i = i step]

где:

  • i — индекс элемента
  • step — базовый шаг задержки

Управление направлением распределения задержек

Помимо линейного увеличения задержки, Motion One позволяет управлять порядком обхода коллекции.

Обратный порядок

animate(
  ".item",
  { opacity: [0, 1] },
  { delay: stagger(0.08, { from: "last" }) }
);

В этом случае анимация начинается с последнего элемента, а первый получает максимальную задержку.

Центрированное распределение

Подход “от центра” формирует радиальный эффект:

animate(
  ".item",
  { scale: [0.8, 1] },
  { delay: stagger(0.05, { from: "center" }) }
);

Такой режим полезен для сеток, где важна визуальная симметрия появления.

Настройка базовой задержки и темпа каскада

Первый аргумент stagger определяет шаг между элементами.

stagger(0.03)
stagger(0.1)
stagger(0.2)

Меньшие значения создают плотную последовательность, большие — выраженный каскад.

Важно учитывать плотность DOM-структуры: при большом количестве элементов чрезмерный шаг задержки приводит к визуальной “разорванности” анимации.

Смещение старта всей группы

Задержка может комбинироваться с общим стартовым смещением:

animate(
  ".item",
  { opacity: [0, 1] },
  {
    delay: stagger(0.05, { start: 0.3 })
  }
);

Здесь:

  • start задаёт глобальную паузу перед началом всей группы
  • stagger добавляет локальные смещения внутри группы

Комбинация этих параметров позволяет строить сложные временные структуры без ручного расчёта каждого элемента.

Ручное управление delay через функцию

В случаях, когда требуется более сложная логика, delay может быть функцией:

animate(
  ".item",
  { opacity: [0, 1] },
  {
    delay: (element, index) => {
      return index * 0.06;
    }
  }
);

Функциональный подход позволяет учитывать:

  • позицию в DOM
  • data-атрибуты
  • размер коллекции
  • внешние состояния

Пример с условием:

delay: (el, i) => {
  return el.dataset.priority === "high" ? 0 : i * 0.05;
}

Комбинирование задержек с трансформациями

Групповые задержки часто применяются совместно с изменением нескольких свойств:

animate(
  ".card",
  {
    opacity: [0, 1],
    transform: ["translateY(30px) scale(0.95)", "translateY(0px) scale(1)"]
  },
  {
    delay: stagger(0.07)
  }
);

При этом каждый элемент проходит одинаковую траекторию, но с временным сдвигом.

Взаимодействие с keyframes

При использовании keyframes задержка влияет только на старт всей последовательности, не нарушая внутреннюю структуру анимации:

animate(
  ".dot",
  {
    y: [20, -10, 0],
    opacity: [0, 1, 1]
  },
  {
    duration: 0.6,
    delay: stagger(0.04)
  }
);

Каждый элемент проходит полный цикл keyframes независимо, но в разное время.

Работа с динамическими списками

При изменении DOM структура задержек пересчитывается на момент запуска анимации.

const items = document.querySelectorAll(".item");

animate(
  items,
  { opacity: [0, 1] },
  { delay: stagger(0.05) }
);

Если элементы добавляются динамически, порядок задержек определяется актуальным состоянием NodeList в момент вызова animate.

Сеточные распределения и визуальные паттерны

Хотя stagger по умолчанию работает как линейная функция индекса, визуально он часто применяется к сеткам.

Типичный эффект “волны” достигается комбинированием направления и шага:

animate(
  ".grid-item",
  { scale: [0.6, 1] },
  { delay: stagger(0.03, { from: "center" }) }
);

Для плотных сеток уменьшение шага задержки критично для предотвращения визуального отставания крайних элементов.

Оптимизация временных последовательностей

При большом количестве элементов важно учитывать суммарную длительность каскада:

Если:

  • шаг задержки = 0.05
  • количество элементов = 100

то последний элемент начнёт анимацию через 5 секунд после первого запуска.

Для оптимизации применяются:

  • уменьшение шага stagger
  • ограничение диапазона from
  • группировка элементов

Сочетание нескольких групп задержек

Разные группы элементов могут иметь независимые временные структуры:

animate(
  ".header-item",
  { opacity: [0, 1] },
  { delay: stagger(0.1) }
);

animate(
  ".content-item",
  { opacity: [0, 1] },
  { delay: stagger(0.03, { from: "last" }) }
);

Такая схема позволяет формировать многослойные сценарии появления интерфейса, где визуальная иерархия задаётся исключительно временными параметрами.