В библиотеке Packery каждый контейнер представляет собой отдельный экземпляр, который управляет размещением своих элементов на сетке. В случаях, когда на странице используется несколько экземпляров Packery, может возникнуть необходимость синхронизировать их поведение — например, для создания комплексных макетов с взаимозависимыми блоками, динамической подстройки размеров или совместного перемещения элементов.
Ключевой момент синхронизации заключается в том, что Packery не предоставляет встроенного механизма для автоматической синхронизации нескольких контейнеров, поэтому требуется использование программных паттернов на стороне Jav * aScript: событий и ручного управления элементами.
Для начала создаются два или более экземпляров:
var grid1 = new Packery('.grid1', {
itemSelector: '.grid-item',
gutter: 10,
});
var grid2 = new Packery('.grid2', {
itemSelector: '.grid-item',
gutter: 10,
});
Каждый экземпляр управляет своим набором элементов, поэтому движение или изменение элемента в одном контейнере не влияет автоматически на другой. Чтобы синхронизировать действия, необходимо использовать события Packery.
Packery генерирует несколько полезных событий:
layoutComplete — вызывается после завершения
перестановки элементов.dragItemPositioned — срабатывает при перемещении
элемента через Draggabilly.removeComplete — после удаления элемента из
контейнера.fitComplete — после того как элемент был «втиснут» в
сетку.Для синхронизации нескольких сеток необходимо подписываться на эти события и обновлять другой экземпляр вручную. Например:
grid1.on('layoutComplete', function() {
grid2.layout(); // Перестроение второго контейнера после изменений в первом
});
grid2.on('dragItemPositioned', function() {
grid1.layout(); // Обновление первого контейнера при перетаскивании элементов во втором
});
Этот подход позволяет поддерживать согласованное расположение элементов между сетками, но требует внимательного контроля, чтобы избежать бесконечных циклов событий.
Иногда требуется не только перестраивать макет, но и переносить элементы между контейнерами. Packery предоставляет методы для добавления и удаления элементов динамически:
// Удаление элемента из grid1
grid1.remove(itemElement);
grid1.layout();
// Добавление элемента в grid2
grid2.appended(itemElement);
grid2.layout();
Важно помнить:
remove() элемент должен быть удалён из DOM или
готов к перемещению.appended() добавляет элемент в DOM контейнера и
включает его в раскладку.Такой подход позволяет перемещать элементы между сетками в реальном времени, сохраняя корректное выравнивание и анимацию.
Packery тесно интегрируется с библиотекой Draggabilly для перетаскивания элементов. Для синхронизации нескольких контейнеров при использовании Draggabilly необходимо:
bindDraggabillyEvents.dragItemPositioned вызывать
перестройку других экземпляров.Пример:
var draggies1 = [];
grid1.getItemElements().forEach(function(itemElem) {
var draggie = new Draggabilly(itemElem);
grid1.bindDraggabillyEvents(draggie);
draggies1.push(draggie);
});
grid1.on('dragItemPositioned', function() {
grid2.layout();
});
Такой механизм обеспечивает динамическую синхронизацию макетов, сохраняя плавность анимации и корректное расположение элементов.
Если высота или ширина контейнера зависит от содержимого, необходимо обновлять размеры всех синхронизированных контейнеров при изменении любого из них:
function syncContainerSizes() {
var maxHeight = Math.max(grid1.element.offsetHeight, grid2.element.offsetHeight);
grid1.element.style.height = maxHeight + 'px';
grid2.element.style.height = maxHeight + 'px';
}
grid1.on('layoutComplete', syncContainerSizes);
grid2.on('layoutComplete', syncContainerSizes);
Это предотвращает разрыв макета и обеспечивает согласованное визуальное восприятие.
При большом количестве элементов или сложных сетках следует учитывать производительность:
requestAnimationFrame для минимизации
количества перестроек.layout() только при действительно
изменившихся элементах.remove() и appended() пакетно, а не по одному,
чтобы сократить количество перерасчётов.Пример с оптимизацией:
var needsLayout = false;
function scheduleLayout() {
if (!needsLayout) {
needsLayout = true;
requestAnimationFrame(function() {
grid1.layout();
grid2.layout();
needsLayout = false;
});
}
}
grid1.on('dragItemPositioned', scheduleLayout);
grid2.on('dragItemPositioned', scheduleLayout);
Такой подход обеспечивает гладкую и отзывчивую синхронизацию даже при интенсивных операциях с элементами.
Основные принципы синхронизации нескольких экземпляров Packery:
layoutComplete,
dragItemPositioned) для уведомления других
экземпляров.remove() и
appended().layout() через пакетную обработку
или requestAnimationFrame.Соблюдение этих правил позволяет строить сложные, взаимозависимые сетки, сохраняя анимацию и стабильность макета на странице.