Packery — это мощная библиотека для создания динамических сеток с элементами различного размера. Одной из ключевых особенностей является возможность разработки кастомных алгоритмов размещения элементов, выходящих за рамки стандартного «masonry»-подхода. Эти алгоритмы позволяют контролировать порядок и положение элементов на сетке, учитывая любые бизнес-правила или визуальные предпочтения.
Кастомный алгоритм размещения реализуется через объект
packer и методы fit и pack.
Основной интерфейс выглядит так:
var customPacker = {
width: 500, // ширина контейнера
height: 0, // высота контейнера, обновляется автоматически
reset: function() { /* сброс внутренних данных */ },
pack: function(item) { /* размещение элемента */ },
fit: function(item) { /* проверка, можно ли разместить элемент */ }
};
width и height — задают
размеры контейнера. Высота вычисляется динамически при добавлении
элементов.reset() — очищает внутренние
структуры, обычно вызывается перед новым циклом размещения.pack(item) — основной метод,
выполняющий размещение конкретного элемента.fit(item) — проверяет, возможно ли
разместить элемент в текущей позиции. Возвращает true или
false.Левый верхний угол (Top-Left Fill) Размещение элементов начинается с верхнего левого угла и продолжается по строкам. Используется, когда важен предсказуемый порядок визуализации.
pack: function(item) {
for (var y = 0; y <= this.height; y += item.height) {
for (var x = 0; x <= this.width; x += item.width) {
item.x = x;
item.y = y;
if (this.fit(item)) return true;
}
}
this.height += item.height;
item.x = 0;
item.y = this.height - item.height;
}Случайное размещение (Random Placement) Позволяет создавать нестандартные, органичные сетки. Основная сложность — избегание пересечений элементов.
fit: function(item) {
var maxAttempts = 100;
for (var i = 0; i < maxAttempts; i++) {
item.x = Math.floor(Math.random() * (this.width - item.width));
item.y = Math.floor(Math.random() * (this.height - item.height));
if (!this.hasCollision(item)) return true;
}
return false;
}Сетка по определённым слотам (Grid-Based Placement) Элементы располагаются по заранее определённым координатам. Используется для точного контроля визуальной структуры.
this.slots = [
{x:0, y:0}, {x:200, y:0}, {x:0, y:200}, {x:200, y:200}
];
pack: function(item) {
for (var i = 0; i < this.slots.length; i++) {
var slot = this.slots[i];
item.x = slot.x;
item.y = slot.y;
if (this.fit(item)) return true;
}
}Ключевая задача кастомного алгоритма — правильная обработка
пересечений элементов. Packery использует метод
getBoundingRect для проверки пересечений:
hasCollision: function(item) {
for (var i = 0; i < this.items.length; i++) {
var placed = this.items[i];
if (
item.x < placed.x + placed.width &&
item.x + item.width > placed.x &&
item.y < placed.y + placed.height &&
item.y + item.height > placed.y
) {
return true;
}
}
return false;
}
Использование этого метода позволяет гарантировать, что каждый элемент займёт свободное место, и сетка останется аккуратной даже при сложных правилах размещения.
Packery поддерживает перераспределение элементов при изменении
размеров контейнера или добавлении новых блоков. Для кастомных
алгоритмов важно реализовать метод reset():
reset: function() {
this.items = [];
this.height = 0;
};
Каждый раз после изменения набора элементов вызывается
pack(item) для корректного перераспределения.
Для подключения кастомного алгоритма используется опция
packer при инициализации:
var grid = new Packery('.grid', {
itemSelector: '.grid-item',
columnWidth: 100,
gutter: 10,
packer: customPacker
});
Packery передаст каждый элемент в методы fit и
pack кастомного объекта, позволяя реализовать любые
нестандартные визуальные схемы.
fit для
ускорения перераспределения при ресайзе.Кастомные алгоритмы размещения в Packery открывают возможности не только для стандартного masonry, но и для сложных, уникальных макетов, адаптирующихся под размеры элементов и контейнера, а также под специфические визуальные требования.