Кастомные алгоритмы размещения

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.

Основные стратегии кастомного размещения

  1. Левый верхний угол (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;
    }
  2. Случайное размещение (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;
    }
  3. Сетка по определённым слотам (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) для корректного перераспределения.

Интеграция с Packery

Для подключения кастомного алгоритма используется опция packer при инициализации:

var grid = new Packery('.grid', {
  itemSelector: '.grid-item',
  columnWidth: 100,
  gutter: 10,
  packer: customPacker
});

Packery передаст каждый элемент в методы fit и pack кастомного объекта, позволяя реализовать любые нестандартные визуальные схемы.

Советы по оптимизации

  • Минимизировать количество проверок коллизий при больших сетках.
  • Использовать массивы свободных слотов вместо перебора всех координат.
  • Для сложных алгоритмов кэшировать результаты fit для ускорения перераспределения при ресайзе.
  • Комбинировать разные стратегии: например, основная сетка + случайное размещение оставшихся элементов.

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