Для работы с библиотекой Packery в Angular-проекте сначала необходимо установить её через npm:
npm install packery
npm install imagesloaded
imagesloaded требуется для корректного позиционирования
элементов, содержащих изображения, поскольку Packery рассчитывает
размеры элементов после их загрузки.
Подключение в компонент:
import { Component, AfterViewInit, ElementRef, ViewChild } from '@angular/core';
import Packery from 'packery';
import imagesLoaded from 'imagesloaded';
Здесь важно использовать AfterViewInit, чтобы инициализация происходила после рендеринга DOM.
HTML-разметка контейнера выглядит следующим образом:
<div #grid class="grid">
<div class="grid-item">Элемент 1</div>
<div class="grid-item">Элемент 2</div>
<div class="grid-item">Элемент 3</div>
<div class="grid-item">Элемент 4</div>
</div>
Ключевые моменты:
#grid используется для доступа к контейнеру
через ViewChild.grid-item.CSS для базового оформления:
.grid {
position: relative;
}
.grid-item {
width: 100px;
height: 100px;
margin: 10px;
background-color: #3498db;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
В компоненте:
@Component({
selector: 'app-packery-grid',
templateUrl: './packery-grid.component.html',
styleUrls: ['./packery-grid.component.css']
})
export class PackeryGridComponent implements AfterViewInit {
@ViewChild('grid') grid!: ElementRef;
private pckry!: Packery;
ngAfterViewInit() {
const gridElement = this.grid.nativeElement;
this.pckry = new Packery(gridElement, {
itemSelector: '.grid-item',
gutter: 10,
percentPosition: true
});
// Обеспечение корректного расположения изображений
imagesLoaded(gridElement, () => {
this.pckry.layout();
});
}
addItem(content: string) {
const item = document.createElement('div');
item.classList.add('grid-item');
item.textContent = content;
this.grid.nativeElement.appendChild(item);
this.pckry.appended(item);
this.pckry.layout();
}
removeItem(index: number) {
const items = this.pckry.getItemElements();
if (items[index]) {
this.pckry.remove(items[index]);
this.pckry.layout();
}
}
}
Особенности и ключевые моменты:
Packery отлично интегрируется с динамическим контентом в Angular,
особенно при использовании *ngFor.
Пример с массивом элементов:
items = ['Элемент A', 'Элемент B', 'Элемент C'];
ngAfterViewInit() {
const gridElement = this.grid.nativeElement;
this.pckry = new Packery(gridElement, {
itemSelector: '.grid-item',
gutter: 10,
percentPosition: true
});
imagesLoaded(gridElement, () => {
this.pckry.layout();
});
}
updateGrid() {
setTimeout(() => {
this.pckry.reloadItems();
this.pckry.layout();
});
}
При изменении массива данных вызывается reloadItems и layout, чтобы сетка корректно пересчитала позиции элементов.
Packery поддерживает несколько событий, полезных для отслеживания действий с элементами:
this.pckry.on('layoutComplete', (laidOutItems) => {
console.log('Сетка выложена, элементов:', laidOutItems.length);
});
this.pckry.on('removeComplete', (removedItems) => {
console.log('Элементы удалены:', removedItems.length);
});
Ключевые события:
Для реализации drag-and-drop используется библиотека Draggabilly:
npm install draggabilly
Пример инициализации:
import Draggabilly from 'draggabilly';
ngAfterViewInit() {
const gridElement = this.grid.nativeElement;
this.pckry = new Packery(gridElement, {
itemSelector: '.grid-item',
gutter: 10,
percentPosition: true
});
const items = this.pckry.getItemElements();
items.forEach((item) => {
const draggie = new Draggabilly(item);
this.pckry.bindDraggabillyEvents(draggie);
});
}
Особенности:
Packery поддерживает адаптивные макеты через процентные размеры или пересчёт позиций при изменении ширины контейнера:
window.addEventListener('resize', () => {
this.pckry.layout();
});
Параметры Packery позволяют гибко управлять сеткой:
| Параметр | Описание |
|---|---|
itemSelector |
CSS-класс элементов, которые будут выложены в сетку |
gutter |
Отступ между элементами (px) |
percentPosition |
Расчёт позиции элементов в процентах |
stamp |
Селектор элементов, которые будут исключены из нормального расположения |
originLeft |
Начало сетки слева (true/false) |
originTop |
Начало сетки сверху (true/false) |
horizontal |
Раскладка по горизонтали вместо вертикали |
Применение stamp позволяет фиксировать элементы на сетке
и обходить их при перестановке других элементов.
Packery в Angular обеспечивает мощный и гибкий инструмент для динамических, перетаскиваемых и адаптивных сеток, полностью интегрируясь с компонентной архитектурой и системой реактивного обновления данных.