Packery управляет расположением элементов на основе алгоритма упаковки прямоугольников. Каждый элемент сетки имеет координаты, которые рассчитываются библиотекой при инициализации и при любых изменениях структуры контейнера. Когда элементы добавляются, удаляются, изменяют размер или перетаскиваются, библиотека должна выполнить перерасчёт координат для сохранения плотной упаковки.
Обновление позиций представляет собой процесс повторного выполнения алгоритма раскладки. Во время этого процесса Packery анализирует текущие размеры элементов, вычисляет доступные области и размещает элементы так, чтобы минимизировать пустое пространство.
Перерасчёт может происходить:
Правильное управление обновлением позиций критически важно для производительности интерфейса и корректной визуальной структуры.
layout()Основной способ принудительного обновления расположения элементов —
метод layout().
Этот метод заставляет Packery пересчитать позиции всех элементов контейнера.
var pckry = new Packery('.grid', {
itemSelector: '.grid-item',
gutter: 10
});
// принудительный перерасчёт
pckry.layout();
При вызове метода происходит:
Метод используется в случаях:
Важно учитывать, что layout() пересчитывает всю
сетку, поэтому частые вызовы могут приводить к заметной
нагрузке на интерфейс.
Изменение размеров элементов напрямую влияет на алгоритм упаковки. Если элемент увеличился или уменьшился, его прежняя позиция может стать недействительной.
Типичная ситуация — изменение высоты карточки после загрузки данных.
item.classList.add('expanded');
pckry.layout();
Без повторного layout могут появиться проблемы:
Packery не отслеживает изменение размеров элементов автоматически, поэтому разработчик должен инициировать перерасчёт.
shiftLayout()Метод shiftLayout() выполняет более мягкий перерасчёт
позиций. В отличие от layout(), он старается сохранить
текущее расположение элементов и лишь корректирует их смещение.
pckry.shiftLayout();
Основные особенности:
Этот метод часто используется после drag-операций или небольших изменений размеров элементов.
Одна из самых распространённых проблем — изменение размеров элементов после загрузки изображений. До загрузки браузер может не знать реальную высоту контента.
В результате:
Для решения используется библиотека imagesLoaded.
imagesLoaded('.grid', function() {
pckry.layout();
});
Такой подход гарантирует, что перерасчёт произойдёт только после загрузки всех изображений.
В более динамичных интерфейсах применяется вариант:
imagesLoaded('.grid').on('progress', function() {
pckry.layout();
});
В этом случае layout обновляется постепенно по мере загрузки изображений.
При динамическом добавлении новых элементов используется метод
appended().
var newItems = document.querySelectorAll('.new-item');
grid.append(...newItems);
pckry.appended(newItems);
Метод выполняет два действия:
После этого обычно вызывается:
pckry.layout();
Если элементы добавляются пакетами, лучше выполнять перерасчёт один раз после всех операций.
Удаление элементов требует освобождения занимаемого пространства.
pckry.remove(element);
pckry.layout();
Packery:
Без вызова layout() в сетке останутся пустые
области.
reloadItems()Если DOM-структура контейнера была изменена напрямую, Packery может потерять актуальное состояние элементов.
В этом случае используется метод reloadItems().
pckry.reloadItems();
pckry.layout();
Метод:
Типичные сценарии применения:
Packery тесно интегрируется с системой перетаскивания. При перемещении элементов происходит автоматическое обновление позиций.
Внутренний механизм работает следующим образом:
После завершения операции выполняется окончательный layout.
Пример подключения:
pckry.bindDraggabillyEvents(draggie);
В большинстве случаев ручной вызов layout() после
drag-операций не требуется.
Ширина контейнера напрямую влияет на размещение элементов. При изменении размеров окна Packery может автоматически перестраивать сетку.
Эта функция контролируется параметром resize.
var pckry = new Packery('.grid', {
resize: true
});
Если автоматический режим отключён, перерасчёт выполняется вручную.
window.addEventListener('resize', function() {
pckry.layout();
});
При частых resize-событиях рекомендуется использовать debounce или throttle, чтобы избежать избыточных перерасчётов.
Частые вызовы layout() могут ухудшить
производительность, особенно при большом количестве элементов.
Основные методы оптимизации:
Вместо нескольких перерасчётов лучше выполнить один.
Плохо:
pckry.appended(item1);
pckry.layout();
pckry.appended(item2);
pckry.layout();
Лучше:
pckry.appended([item1, item2]);
pckry.layout();
Использование requestAnimationFrame помогает
синхронизировать обновление с циклом отрисовки браузера.
requestAnimationFrame(function() {
pckry.layout();
});
let timeout;
window.addEventListener('resize', function() {
clearTimeout(timeout);
timeout = setTimeout(function() {
pckry.layout();
}, 200);
});
Такой подход предотвращает десятки перерасчётов при изменении размеров окна.
Фильтрация часто выполняется через скрытие элементов.
element.style.display = 'none';
pckry.layout();
После скрытия Packery пересчитывает расположение оставшихся элементов.
Если элементы снова отображаются:
element.style.display = '';
pckry.layout();
Альтернативный вариант — временное удаление элементов из системы Packery и их повторное добавление.
Некорректное обновление позиций может проявляться в нескольких формах:
Наиболее распространённые причины:
1. Отсутствие вызова layout()
После изменения размеров элементов сетка не пересчитывается.
2. Асинхронная загрузка контента
Изображения и данные изменяют размеры карточек после первоначальной раскладки.
3. Прямое изменение DOM
Если элементы добавляются без использования API Packery, библиотека не знает о новых объектах.
Рекомендуемая последовательность действий:
pckry.reloadItems();
pckry.layout();
При обновлении layout Packery использует внутреннюю систему rect packing.
Основные этапы:
Этот алгоритм обеспечивает:
При каждом вызове layout() структура свободных областей
строится заново, что позволяет корректно учитывать любые изменения
размеров элементов.