Миграция с Packery

Isotope и Packery — это библиотеки для создания динамических сеток с возможностью фильтрации, сортировки и позиционирования элементов. Несмотря на схожесть, у этих библиотек различный подход к управлению позициями элементов: Packery опирается на концепцию «свободного позиционирования» элементов, в то время как Isotope использует гибкую сетку с поддержкой анимации, фильтров и сортировки.

Основные отличия подходов

  • Packery: элементы располагаются с учётом свободного пространства, используя алгоритм «Bin Packing». Позиции элементов могут быть произвольными, что удобно для нестандартных макетов.
  • Isotope: сетка организована с жёсткой логикой колонок и строк, элементы распределяются по выбранному layoutMode (masonry, fitRows, vertical). Анимация и фильтрация выполняются автоматически, без ручного контроля позиции каждого элемента.

Понимание этих различий критично при миграции: логика позиционирования в Packery часто завязана на абсолютные координаты, а в Isotope важна привязка к контейнеру и layoutMode.

Инициализация контейнера

В Packery контейнер инициализировался через:

var pckry = new Packery('.grid', {
  itemSelector: '.grid-item',
  gutter: 10
});

В Isotope аналогичная инициализация выглядит так:

var iso = new Isotope('.grid', {
  itemSelector: '.grid-item',
  layoutMode: 'masonry',
  masonry: {
    gutter: 10
  }
});

Ключевые моменты:

  • layoutMode выбирает способ расположения элементов (masonry, fitRows, vertical).
  • Параметр masonry.gutter заменяет настройку gutter в Packery.
  • Isotope автоматически отслеживает изменения размеров элементов и контейнера через встроенную анимацию.

Фильтрация элементов

Packery использует комбинацию с element.style.display или внешними библиотеками для фильтрации:

var items = pckry.getItemElements();
items.forEach(function(item) {
  if (!item.classList.contains('active')) {
    item.style.display = 'none';
  }
});
pckry.layout();

В Isotope фильтрация встроена напрямую:

iso.arrange({ filter: '.active' });

Преимущества:

  • Нет необходимости вручную изменять display элементов.
  • Поддерживается анимация при скрытии и показе элементов.
  • Можно использовать сложные CSS-селекторы (.category1.active, :not(.disabled)).

Сортировка элементов

Packery не предоставляет встроенной сортировки. Для сортировки приходилось вручную переставлять элементы в DOM и вызывать layout().

Isotope поддерживает сортировку через getSortData и sortBy:

var iso = new Isotope('.grid', {
  itemSelector: '.grid-item',
  getSortData: {
    name: '.name',          // текст внутри элемента
    date: '[data-date]'     // дата из атрибута
  }
});

iso.arrange({ sortBy: 'date', sortAscending: true });

Особенности миграции:

  • Необходима подготовка данных для сортировки (например, атрибуты data-*).
  • Isotope обеспечивает плавную анимацию перестановки элементов.

Работа с динамическими элементами

Добавление и удаление элементов в Packery требовало явного вызова методов:

pckry.appended(newElements);
pckry.layout();

В Isotope это делается через appended и remove:

// Добавление
iso.appended(newElements);

// Удаление
iso.remove(removedElements);
iso.layout();

Замечания:

  • При использовании фильтров новые элементы автоматически подчиняются текущему фильтру.
  • Методы layout и arrange могут вызываться после массовых изменений элементов для корректной анимации.

Настройка анимации

Packery использовал библиотеку Draggabilly для drag-and-drop и требовал внешних решений для анимации.

Isotope имеет встроенные возможности анимации:

var iso = new Isotope('.grid', {
  itemSelector: '.grid-item',
  transitionDuration: '0.4s'
});

Параметры анимации:

  • transitionDuration — продолжительность анимации.
  • hiddenStyle и visibleStyle позволяют кастомизировать анимацию при фильтрации элементов.
hiddenStyle: { opacity: 0, transform: 'scale(0.8)' },
visibleStyle: { opacity: 1, transform: 'scale(1)' }

Особенности при переносе кастомных макетов

  • Сетка с фиксированными колонками: в Isotope используется fitRows или masonry с заданной шириной колонок.
  • Сетки со свободным позиционированием: полностью имитировать Packery в Isotope невозможно, но masonry с гибкой шириной элементов и percentPosition: true позволяет приблизиться к исходной верстке.
var iso = new Isotope('.grid', {
  itemSelector: '.grid-item',
  layoutMode: 'masonry',
  masonry: { columnWidth: '.grid-sizer', percentPosition: true }
});
  • Для сохранения размеров элементов и предотвращения «перескакивания» при фильтрации рекомендуется использовать невидимый элемент-спейсер (.grid-sizer).

Дополнительные рекомендации

  • Для интерактивных сеток с перетаскиванием элементов можно совместить Isotope с Draggable из библиотеки GSAP.
  • Если есть зависимость от событий Packery (dragItemPositioned, layoutComplete), их можно заменить на Isotope события: arrangeComplete, layoutComplete, removeComplete.
  • Оптимизация больших сеток достигается через imagesLoaded для корректного расчета размеров изображений перед инициализацией:
imagesLoaded('.grid', function() {
  iso.layout();
});
  • При необходимости комбинирования фильтрации и сортировки Isotope позволяет вызывать arrange с несколькими параметрами одновременно:
iso.arrange({
  filter: '.active',
  sortBy: 'name',
  sortAscending: true
});

Миграция с Packery на Isotope требует внимательного подхода к позиционированию и логике анимации, но позволяет получить более гибкую и управляемую сетку с встроенными инструментами фильтрации, сортировки и анимации элементов.