Библиотека Packery реализует динамическую сеточную компоновку элементов, в которой каждый элемент может занимать произвольное количество пространства. Одной из важных возможностей является изменение размеров элементов после инициализации сетки. При этом библиотека автоматически перераспределяет элементы, устраняя пустоты и оптимизируя размещение.
Изменение размеров может происходить в нескольких сценариях:
width,
height)После изменения размеров требуется пересчитать расположение элементов, чтобы Packery корректно разместил элементы внутри контейнера.
Основной метод для этого — layout().
Если размеры элемента изменяются через JavaScript или CSS, Packery не всегда автоматически пересчитывает сетку. В таком случае используется метод:
pckry.layout();
Пример:
var grid = document.querySelector('.grid');
var pckry = new Packery(grid, {
itemSelector: '.grid-item',
gutter: 10
});
var item = grid.querySelector('.grid-item');
item.style.width = '300px';
pckry.layout();
Процесс происходит следующим образом:
Packery использует алгоритм бин-пэкинга, который минимизирует свободные пространства внутри контейнера.
stamp() при изменении размеровЕсли элемент должен оставаться фиксированным и не
участвовать в перестройке сетки, используется метод
stamp().
pckry.stamp(element);
pckry.layout();
Пример:
var fixedItem = document.querySelector('.fixed-item');
pckry.stamp(fixedItem);
fixedItem.style.width = '400px';
pckry.layout();
В этом случае:
Метод полезен для:
Для интерактивного изменения размеров обычно используется библиотека Resizable. Наиболее распространённое решение — jQuery UI Resizable.
Пример интеграции:
$('.grid-item').resizable({
stop: function() {
pckry.layout();
}
});
Когда пользователь завершает изменение размера:
stop срабатываетlayout()Это обеспечивает плавное интерактивное изменение интерфейса.
Современный способ отслеживания изменений размеров — API ResizeObserver. Этот механизм автоматически отслеживает изменение размеров DOM-элементов.
Пример:
const observer = new ResizeObserver(() => {
pckry.layout();
});
document.querySelectorAll('.grid-item').forEach(item => {
observer.observe(item);
});
Преимущества:
ResizeObserver особенно полезен при:
Распространённый подход — изменение размеров элементов через переключение CSS-классов.
CSS:
.grid-item {
width: 150px;
height: 150px;
}
.grid-item.large {
width: 300px;
height: 300px;
}
Jav * aScript:
item.classList.toggle('large');
pckry.layout();
Этот подход используется для:
Изменение размеров можно сопровождать CSS-анимациями. Packery корректно работает вместе с CSS transitions.
CSS:
.grid-item {
transition: width 0.4s, height 0.4s;
}
Jav * aScript:
item.classList.add('large');
setTimeout(function() {
pckry.layout();
}, 400);
Алгоритм работы:
layout()Частая проблема — изображения изменяют размеры карточек после загрузки. Если Packery рассчитывает сетку до загрузки изображений, компоновка может нарушиться.
Для решения используется библиотека imagesLoaded.
Пример:
imagesLoaded(grid, function() {
pckry.layout();
});
Логика:
Иногда размеры элементов задаются в кратных значениях сетки.
Пример:
.grid-sizer {
width: 100px;
}
.grid-item {
width: 100px;
}
.grid-item--width2 {
width: 200px;
}
.grid-item--height2 {
height: 200px;
}
Инициализация Packery:
var pckry = new Packery('.grid', {
itemSelector: '.grid-item',
columnWidth: '.grid-sizer'
});
Изменение размеров:
item.classList.add('grid-item--width2');
pckry.layout();
Такой подход позволяет создавать гибкую модульную систему размеров.
Если изменился только один элемент, можно оптимизировать работу.
Используется метод layoutItems():
pckry.layoutItems([element]);
Пример:
item.style.width = '250px';
pckry.layoutItems([item]);
Это снижает нагрузку, поскольку пересчитывается только часть сетки.
Иногда Packery должен повторно измерить размеры элементов. Для этого
используется метод reloadItems().
pckry.reloadItems();
pckry.layout();
Этот метод:
Используется после:
Частые вызовы layout() могут снижать производительность.
Для оптимизации применяются следующие подходы:
Дебаунс
let timer;
function updateLayout() {
clearTimeout(timer);
timer = setTimeout(() => {
pckry.layout();
}, 100);
}
Batch-обновления
items.forEach(item => {
item.classList.add('large');
});
pckry.layout();
Один вызов layout() значительно быстрее, чем серия
вызовов.
Packery часто используется вместе с Draggabilly.
При изменении размеров перетаскиваемых элементов важно обновлять компоновку.
Пример:
var draggie = new Draggabilly(item);
pckry.bindDraggabillyEvents(draggie);
item.classList.add('large');
pckry.layout();
Если пользователь изменяет размер элемента, сетка продолжает корректно поддерживать перетаскивание и позиционирование.
Популярный интерфейсный паттерн — раскрывающиеся карточки.
Пример:
item.addEventListener('click', function() {
this.classList.toggle('expanded');
pckry.layout();
});
CSS:
.grid-item.expanded {
width: 300px;
height: 300px;
}
Такая архитектура используется в:
При изменении размеров элементов Packery выполняет несколько этапов:
Этот процесс обеспечивает:
При работе с изменением размеров элементов в Packery важно соблюдать несколько правил:
Всегда вызывать layout() после изменения
размеров
Без перерасчёта сетка может содержать пустоты.
Избегать частых вызовов layout
Частые пересчёты создают лишнюю нагрузку.
Использовать ResizeObserver
Это самый надёжный способ отслеживания изменений.
Использовать модульные размеры
Сетка становится предсказуемой и легко управляемой.
Контролировать загрузку изображений
Изображения — частая причина нарушения компоновки.
Поддержка изменения размеров элементов делает Packery удобным инструментом для построения сложных интерфейсов:
Гибкая система перерасчёта позволяет менять размеры элементов в любой момент жизненного цикла приложения, сохраняя корректную компоновку интерфейса.