Packery — это режим компоновки элементов в библиотеке Isotope, предназначенный для создания плотной мозаичной сетки без фиксированной структуры строк и колонок. Алгоритм стремится максимально эффективно заполнять свободное пространство контейнера, располагая элементы различного размера так, чтобы минимизировать пустоты.
В отличие от стандартных сеточных режимов, Packery применяет принцип двумерной упаковки прямоугольников. Элементы располагаются не только слева направо и сверху вниз, но и могут занимать свободные области, образовавшиеся после размещения предыдущих блоков.
Ключевые особенности режима:
Алгоритм Packery схож с механизмами, применяемыми в библиотеке Packery, на которой частично основана реализация в Isotope.
Для использования режима необходимо подключить:
<script src="isotope.pkgd.min.js"></script>
После подключения режим становится доступным через параметр
layoutMode.
Минимальная конфигурация:
var iso = new Isotope('.grid', {
itemSelector: '.grid-item',
layoutMode: 'packery'
});
HTML-структура:
<div class="grid">
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--width2"></div>
<div class="grid-item"></div>
</div>
CSS-пример:
.grid-item {
width: 100px;
height: 100px;
}
.grid-item--width2 {
width: 200px;
}
После инициализации Isotope автоматически рассчитывает расположение элементов.
Алгоритм Packery выполняет несколько этапов:
Определяется:
Алгоритм формирует список доступных прямоугольных областей внутри контейнера.
Для каждого элемента выбирается первая область, в которую он помещается.
После размещения элемент “разрезает” доступную область на новые свободные участки.
Таким образом формируется плотная мозаичная структура.
columnWidth задаёт базовую ширину колонок, используемую
при расчёте сетки.
var iso = new Isotope('.grid', {
layoutMode: 'packery',
packery: {
columnWidth: 100
}
});
Поведение:
Использование DOM-элемента как эталона:
packery: {
columnWidth: '.grid-sizer'
}
HTML:
<div class="grid">
<div class="grid-sizer"></div>
<div class="grid-item"></div>
</div>
Это позволяет адаптировать сетку под responsive-дизайн.
gutter задаёт расстояние между элементами.
packery: {
gutter: 10
}
Эффект:
Использование отдельного элемента:
packery: {
gutter: '.gutter-sizer'
}
По умолчанию Packery размещает элементы вертикально. Для
горизонтального режима используется опция horizontal.
packery: {
horizontal: true
}
Особенности:
Каждый элемент получает координаты top и
left, рассчитанные алгоритмом Packery.
Isotope применяет позиционирование через CSS:
.grid-item {
position: absolute;
}
Контейнер:
.grid {
position: relative;
}
Такой подход обеспечивает:
Isotope автоматически анимирует перемещение элементов при изменении макета.
Причины перестройки:
Пример добавления элементов:
iso.appended(newItems);
iso.layout();
Элементы плавно перемещаются в новые позиции.
Packery особенно эффективен при использовании блоков различной ширины и высоты.
Пример:
.grid-item {
width: 100px;
height: 100px;
}
.grid-item--width2 {
width: 200px;
}
.grid-item--height2 {
height: 200px;
}
HTML:
<div class="grid-item grid-item--width2"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
Алгоритм:
Packery поддерживает drag-and-drop.
Для этого используется библиотека:
Пример с Draggabilly:
var grid = document.querySelector('.grid');
var iso = new Isotope(grid, {
layoutMode: 'packery',
itemSelector: '.grid-item'
});
iso.getItemElements().forEach(function(itemElem) {
var draggie = new Draggabilly(itemElem);
iso.bindDraggabillyEvents(draggie);
});
После этого элементы можно свободно перемещать внутри контейнера.
Алгоритм автоматически:
Новые элементы могут добавляться динамически.
var items = document.createElement('div');
items.className = 'grid-item';
grid.appendChild(items);
iso.appended(items);
После добавления:
Удаление также вызывает перестройку сетки.
iso.remove(element);
iso.layout();
Освободившееся пространство автоматически заполняется соседними блоками.
Packery полностью совместим с механизмом фильтрации Isotope.
Пример:
iso.arrange({
filter: '.category-a'
});
После фильтрации:
Сортировка влияет на порядок размещения элементов.
iso.arrange({
sortBy: 'name'
});
После изменения порядка Packery:
Packery корректно работает с responsive-версткой.
При изменении ширины контейнера выполняется:
iso.layout();
На практике это обычно происходит автоматически при изменении размеров окна браузера.
Пример:
window.addEventListener('resize', function() {
iso.layout();
});
При работе с большим количеством элементов важно учитывать несколько правил.
Массовые изменения лучше выполнять пакетно:
iso.arrange({
filter: '*'
});
а затем вызывать layout() один раз.
Isotope применяет transform: translate() вместо
изменения top и left, что:
Изображения могут менять размеры элементов после загрузки. Для предотвращения скачков используется библиотека:
imagesLoaded
imagesLoaded(grid, function() {
iso.layout();
});
Packery широко применяется для интерфейсов с динамическим контентом:
элементы различного размера формируют плотную мозаику.
используются для:
Packery позволяет пользователю:
В библиотеке Isotope также доступен режим masonry.
Основные различия:
| Характеристика | Masonry | Packery |
|---|---|---|
| Структура | колонковая | свободная |
| Заполнение пустот | ограниченное | максимально плотное |
| Перетаскивание | нет | поддерживается |
| Сетка | строгая | гибкая |
Packery обеспечивает более естественную мозаичную структуру.
Несмотря на гибкость, режим имеет ряд особенностей:
Также важно учитывать, что алгоритм не всегда гарантирует идеальную плотность упаковки, поскольку работает в рамках быстрого приближенного решения.
Packery использует систему координат контейнера:
(0,0) — левый верхний уголx и
yСтруктура размещения хранит:
При каждом изменении выполняется пересчёт этих структур.
Иногда требуется вручную инициировать обновление расположения.
Методы:
iso.layout();
пересчитывает позиции без изменения данных.
iso.reloadItems();
пересчитывает список элементов.
iso.arrange();
выполняет полную операцию:
Режим Packery часто используется совместно с другими возможностями Isotope:
В результате формируются гибкие интерфейсы с интерактивной мозаичной компоновкой, эффективно использующей пространство контейнера.