Принцип работы stagger

Stagger-подход в анимации представляет собой способ последовательного или распределённого запуска одинаковых анимационных эффектов по множеству элементов с контролируемыми смещениями во времени, пространстве или параметрах. В контексте mo.js этот механизм становится ключевым инструментом построения сложных сцен, где множество объектов должны вести себя синхронно по логике, но асинхронно по исполнению.

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


Базовая модель распределения значений

В stagger-логике используется функция распределения, которая принимает индекс элемента и общее количество элементов, возвращая изменённый параметр:

  • индекс элемента
  • общее количество элементов
  • конфигурацию распределения

Формально это можно представить как преобразование:

value(i) = base + delta(i / total)

Где delta может быть линейной, экспоненциальной, синусоидальной или произвольной функцией.

В mo.js подобное поведение реализуется через функции и встроенные stagger-хелперы, которые автоматически интерполируют значения.


Последовательный stagger (time offset)

Наиболее распространённый вариант — временной сдвиг анимаций. Каждый следующий элемент стартует позже предыдущего.

const tween = new mojs.Tween({
  duration: 1000,
  delay: (el, i) => i * 100,
  onUpdate: (progress) => {
    el.style.transform = `translateX(${progress * 100}px)`;
  }
});

Ключевая идея — линейная зависимость задержки от индекса:

  • первый элемент запускается сразу
  • каждый следующий получает дополнительную задержку
  • формируется эффект волны

Подобная модель используется в UI-анимациях появления списков, сеток и групп объектов.


Пространственный stagger

Stagger применяется не только ко времени, но и к координатам. В этом случае элементы получают смещения в пространстве, создавая эффект развертывания или волны.

const shift = i => ({
  x: i * 10,
  y: Math.sin(i * 0.5) * 20
});

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


Grid-stagger и работа с сетками

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

Stagger в сетке вычисляется через координаты:

  • row (строка)
  • column (колонка)
  • distance from origin
  • диагональная позиция

Пример логики:

const stagger = (i, total) => {
  const cols = 10;
  const row = Math.floor(i / cols);
  const col = i % cols;

  return {
    delay: (row + col) * 50
  };
};

Такой способ позволяет формировать:

  • диагональные волны
  • радиальные распространения
  • «перекатывающиеся» анимации

Радиальный stagger

Особый случай — распространение от центра. Элементы анимируются в зависимости от расстояния до точки источника.

const distance = (x, y) => Math.sqrt(x * x + y * y);

const stagger = (i, positions) => {
  const d = distance(positions[i].x, positions[i].y);

  return {
    delay: d * 10
  };
};

Эффект напоминает:

  • ударную волну
  • всплеск энергии
  • распространение импульса

Функциональный stagger как базовая абстракция

В mo.js stagger не ограничивается линейными вычислениями. Любой параметр может быть функцией:

  • длительность
  • задержка
  • масштаб
  • поворот
  • прозрачность

Общий шаблон:

param: (el, i, total) => f(i, total)

Гибкость этого подхода позволяет создавать нелинейные распределения.


Нелинейные распределения

Линейное увеличение редко используется в сложных сценах. Чаще применяются функции:

Экспоненциальное распределение

delay: i => Math.pow(i, 1.5) * 20

Эффект:

  • резкое ускорение в конце
  • плотная начальная группа

Синусоидальное распределение

y: i => Math.sin(i * 0.3) * 30

Эффект:

  • волнообразные структуры
  • органическое движение

Обратное распределение

scale: i => 1 - i / total

Эффект:

  • затухание
  • распад структуры

Stagger через ключевые массивы значений

В mo.js часто применяется метод распределения через массивы:

const values = [0, 50, 100, 50, 0];

delay: (el, i) => values[i % values.length]

Это позволяет:

  • задавать произвольные паттерны
  • повторять сложные циклы
  • создавать ритмические структуры

Комбинирование stagger-параметров

Сложные эффекты формируются при одновременном применении нескольких stagger-функций:

  • задержка + масштаб
  • позиция + прозрачность
  • вращение + смещение
const config = {
  delay: i => i * 30,
  scale: i => 1 + i * 0.1,
  opacity: i => 1 - i * 0.05
};

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


Влияние порядка элементов

Stagger напрямую зависит от порядка входной коллекции. Изменение порядка приводит к изменению всей динамики сцены.

Особенно критично для:

  • DOM NodeList
  • массивов SVG-элементов
  • canvas-объектов

Сортировка элементов по координатам может радикально изменить визуальный результат.


Случайный stagger и детерминированность

Добавление случайности позволяет разрушить механическую структуру:

delay: i => i * 50 + Math.random() * 100

Однако в системах с повторяемой анимацией часто используется псевдослучайность с фиксированным seed-подходом, чтобы сохранить воспроизводимость.


Оптимизация вычислений stagger

При большом количестве элементов stagger-функции становятся узким местом. Оптимизация достигается через:

  • предвычисление массивов значений
  • кэширование результатов функций
  • минимизацию математических операций внутри callback
const delays = Array.from({ length: total }, (_, i) => i * 20);

Stagger как система координат анимации

Stagger в mo.js фактически превращается в альтернативную систему координат, где каждый элемент имеет:

  • временную координату (delay)
  • пространственную координату (x, y, z)
  • параметрическую координату (scale, rotate, opacity)

Таким образом создаётся многомерное поле анимации, где поведение каждого объекта определяется его положением в абстрактном пространстве индексов.


Связь stagger с timeline-моделями

В timeline-анимации stagger становится механизмом декомпозиции общей сцены на микро-события.

Каждый элемент:

  • получает собственный стартовый offset
  • участвует в общей временной оси
  • сохраняет синхронизацию с глобальным прогрессом

Это позволяет строить:

  • каскадные появления
  • развертки интерфейсов
  • синхронные переходы с асинхронной подачей элементов