Пересчет layout при ресайзе

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

Автоматический пересчет layout

По умолчанию Packery способен автоматически реагировать на изменения размеров контейнера, если задан параметр resize: true при инициализации. Это позволяет библиотеке слушать событие window.resize и запускать пересчет элементов:

var grid = document.querySelector('.grid');
var pckry = new Packery(grid, {
  itemSelector: '.grid-item',
  gutter: 10,
  resize: true
});

Пояснение ключевых параметров:

  • itemSelector — CSS-селектор для элементов сетки, которые будут позиционироваться.
  • gutter — отступ между элементами сетки, учитываемый при пересчете.
  • resize — включает автоматический пересчет layout при изменении размеров окна.

Когда активирован resize: true, Packery использует внутренний метод fit для каждого элемента, проверяя их положение и корректируя при необходимости.

Ручной пересчет layout

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

  • контейнер меняет размеры динамически без изменения размеров окна;
  • требуется пересчет после загрузки изображений, изменение контента внутри элементов или асинхронной подгрузки новых блоков.

Для таких сценариев используется метод layout():

pckry.layout();

Этот вызов пересчитывает позиции всех элементов и размещает их согласно текущим настройкам сетки. Часто layout() используют совместно с imagesLoaded, чтобы дождаться полной загрузки изображений и избежать «скачков» элементов:

imagesLoaded(grid, function() {
  pckry.layout();
});

Оптимизация пересчета при ресайзе

Событие resize в браузере может срабатывать десятки раз в секунду, что создаёт нагрузку при постоянном вызове layout(). Для повышения производительности используют debounce:

function debounce(fn, delay) {
  let timeout;
  return function() {
    clearTimeout(timeout);
    timeout = setTimeout(fn, delay);
  };
}

window.addEventListener('resize', debounce(function() {
  pckry.layout();
}, 150));

Debounce позволяет вызвать пересчет только один раз после того, как изменение размера прекратилось на заданный интервал (150 мс в примере). Это предотвращает лишние перерасчеты и повышает плавность интерфейса.

Взаимодействие с динамическим контентом

При добавлении новых элементов в сетку после инициализации, необходимо не только добавить элементы в DOM, но и зарегистрировать их в Packery:

var newItem = document.createElement('div');
newItem.className = 'grid-item';
grid.appendChild(newItem);

pckry.appended(newItem);
pckry.layout();

Метод appended сообщает Packery о появлении новых элементов, после чего layout() размещает их корректно, учитывая существующие блоки и отступы.

Обновление размеров отдельных элементов

Если размеры отдельных элементов изменяются динамически (например, растягиваются по контенту), можно использовать метод fit для конкретного элемента:

pckry.fit(newItem);

Метод fit подбирает оптимальную позицию для элемента без полного пересчета сетки. Это полезно для плавной анимации или при интерактивных изменениях контента.

События, связанные с layout

Packery предоставляет события, которые помогают контролировать процесс пересчета:

  • layoutComplete — срабатывает после завершения всех пересчетов layout.
  • dragItemPositioned — вызывается, когда элемент был перемещен пользователем и Packery закончил его размещение.
  • removeComplete — уведомляет об успешном удалении элементов из сетки и пересчете layout.

Пример использования события layoutComplete:

pckry.on('layoutComplete', function(laidOutItems) {
  console.log('Layout пересчитан для элементов:', laidOutItems);
});

Эти события позволяют интегрировать Packery с другими скриптами и выполнять дополнительные действия после изменения сетки.

Рекомендации по стабильному layout при ресайзе

  1. Всегда включать resize: true для автоматического пересчета.
  2. Использовать imagesLoaded для корректного позиционирования элементов с изображениями.
  3. Применять debounce или throttle для событий resize, чтобы минимизировать нагрузку.
  4. Для динамического контента применять методы appended и layout().
  5. Использовать fit для отдельных элементов при небольших изменениях размера.
  6. Отслеживать события Packery, чтобы выполнять действия после завершения layout, например анимацию или обновление других компонентов интерфейса.

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