Stagger эффекты

Stagger эффекты в библиотеке Masonry позволяют анимировать элементы сетки с постепенной задержкой, создавая визуально привлекательное распределение элементов при загрузке или перестройке сетки. Использование stagger обеспечивает ощущение динамики и плавного появления элементов, что особенно важно для сложных интерфейсов с большим количеством карточек или изображений.

В Masonry классический способ управления анимацией заключается в сочетании CSS-переходов с параметром transitionDuration, но для реализации stagger эффектов требуется дополнительная настройка временных задержек для отдельных элементов.


Настройка анимации через CSS

Masonry не имеет встроенного параметра stagger, однако его можно эмулировать с помощью CSS-переходов и JavaScript. Например, для карточек сетки задаются базовые стили:

.grid-item {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.4s ease, transform 0.4s ease;
}
.grid-item.show {
  opacity: 1;
  transform: translateY(0);
}

Каждому элементу при появлении добавляется класс .show, а временная задержка реализуется через динамическое добавление transition-delay.


Реализация stagger с помощью JavaScript

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

const gridItems = document.querySelectorAll('.grid-item');
gridItems.forEach((item, index) => {
  const delay = index * 100; // задержка в миллисекундах
  setTimeout(() => {
    item.classList.add('show');
  }, delay);
});

В этом примере каждый последующий элемент появляется с задержкой 100 мс относительно предыдущего. Такой подход дает ощущение “каскада” появления, что часто используется при загрузке больших сеток изображений.


Интеграция stagger с Masonry

Чтобы stagger эффект корректно работал при перестроении сетки после фильтрации или добавления новых элементов, необходимо комбинировать Masonry API и управление классами анимации.

Пример инициализации Masonry с динамическим добавлением новых элементов:

const grid = document.querySelector('.grid');
const msnry = new Masonry(grid, {
  itemSelector: '.grid-item',
  columnWidth: '.grid-sizer',
  percentPosition: true
});

function addItems(newItems) {
  newItems.forEach((item, index) => {
    grid.appendChild(item);
    const delay = index * 100;
    setTimeout(() => {
      item.classList.add('show');
      msnry.appended(item);
      msnry.layout();
    }, delay);
  });
}

В этом коде каждый новый элемент получает stagger задержку при добавлении в сетку. Masonry автоматически перераспределяет элементы после добавления и применения анимации.


Контроль продолжительности и направления

Stagger эффекты можно гибко настраивать:

  • Изменение задержки: увеличение значения index * delay замедляет появление элементов.
  • Обратный порядок: используя Array.from(gridItems).reverse() можно анимировать элементы справа налево или снизу вверх.
  • Комбинированные эффекты: помимо opacity и transform, можно анимировать scale, rotate и другие CSS-свойства для более выразительных переходов.
.grid-item.show {
  opacity: 1;
  transform: translateY(0) scale(1);
}
const delay = index * 80; // более плотный stagger
item.style.transitionDelay = `${delay}ms`;

Stagger при фильтрации и сортировке

При динамической фильтрации сетки важно пересчитывать порядок элементов и применять stagger заново:

function filterItems(category) {
  const items = grid.querySelectorAll('.grid-item');
  const visibleItems = Array.from(items).filter(item => item.dataset.category === category);

  items.forEach(item => item.classList.remove('show'));
  
  visibleItems.forEach((item, index) => {
    const delay = index * 120;
    setTimeout(() => item.classList.add('show'), delay);
  });

  msnry.layout();
}

Это позволяет не только плавно скрывать элементы, но и анимированно показывать только отфильтрованные карточки с сохранением stagger эффекта.


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

При больших сетках с сотнями элементов необходимо учитывать нагрузку на рендеринг:

  • Использовать requestAnimationFrame вместо setTimeout для более плавной анимации.
  • Ограничивать количество одновременно анимируемых элементов (например, анимировать пакетами по 20–30 элементов).
  • Минимизировать использование тяжелых CSS-свойств (например, box-shadow или сложные фильтры) во время анимации.

Пример с requestAnimationFrame:

function staggerShow(items, delay = 100) {
  items.forEach((item, index) => {
    const startTime = performance.now() + index * delay;
    function animate(time) {
      if (time >= startTime) item.classList.add('show');
      else requestAnimationFrame(animate);
    }
    requestAnimationFrame(animate);
  });
}

Такой подход гарантирует синхронизацию анимации с частотой кадров браузера, снижая “подергивания” и задержки.


Сочетание с библиотеками анимации

Для более сложных stagger эффектов можно комбинировать Masonry с библиотеками вроде GSAP или Anime.js, позволяя:

  • Плавно управлять временными кривыми (ease, power2.out).
  • Анимировать несколько свойств одновременно.
  • Реализовывать сложные цепочки анимаций при добавлении, фильтрации или сортировке элементов.

Пример интеграции с GSAP:

gsap.fromTo('.grid-item', 
  { opacity: 0, y: 20 }, 
  { opacity: 1, y: 0, stagger: 0.1, ease: "power2.out" }
);

Такой подход делает stagger эффекты более выразительными и позволяет создавать интерактивные и динамичные интерфейсы без потери производительности.