Алгоритм упаковки

Библиотека Packery реализует алгоритм пространственной упаковки элементов внутри контейнера. Основная задача алгоритма — размещение блоков различного размера таким образом, чтобы минимизировать пустоты и максимально эффективно использовать доступное пространство.

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

Алгоритм относится к классу задач двумерной упаковки (2D bin packing) — широко известной вычислительной проблеме, применяемой в оптимизации пространства, компоновке интерфейсов, системах хранения и производстве.


Базовая модель размещения

Алгоритм Packery работает на основе нескольких ключевых сущностей:

Контейнер — область, внутри которой размещаются элементы.

Элементы (items) — блоки различного размера, которые необходимо расположить.

Свободные области (spaces) — прямоугольные области контейнера, ещё не занятые элементами.

Каждый новый элемент помещается в одну из свободных областей. После размещения алгоритм пересчитывает оставшиеся свободные зоны.

Таким образом, структура макета формируется итеративно:

  1. создаётся начальная свободная область, равная размеру контейнера;
  2. первый элемент занимает часть пространства;
  3. оставшаяся область разбивается на новые свободные зоны;
  4. следующий элемент помещается в одну из них;
  5. процесс повторяется до размещения всех элементов.

Пространственная модель

Свободные области представлены прямоугольниками. Каждый прямоугольник описывается параметрами:

  • координата X
  • координата Y
  • ширина
  • высота

Пример структуры свободной области:

Space {
  x: 0,
  y: 0,
  width: 800,
  height: 600
}

После размещения элемента свободное пространство делится на несколько новых областей. Например, если элемент занимает верхний левый угол контейнера, остаются две зоны:

  • справа от элемента
  • под элементом

Графически это выглядит следующим образом.

+-----------------------+
| item |                |
|      |     space      |
+------+----------------+
|         space         |
+-----------------------+

Процесс поиска позиции

Каждый элемент проходит несколько этапов размещения.

1. Проверка доступных областей

Алгоритм перебирает список свободных пространств и проверяет, помещается ли элемент внутри каждого из них.

Проверка выполняется по условиям:

item.width  <= space.width
item.height <= space.height

Если условие выполняется, пространство считается кандидатом для размещения.


2. Выбор оптимальной позиции

Если найдено несколько подходящих областей, алгоритм выбирает одну из них. В Packery используется стратегия, близкая к first-fit placement — первый подходящий участок пространства.

Дополнительно учитываются:

  • положение элемента ближе к верхнему левому углу
  • минимизация фрагментации пространства
  • соответствие ориентации контейнера (вертикальная или горизонтальная компоновка)

3. Размещение элемента

После выбора области элемент получает координаты:

item.x = space.x
item.y = space.y

Эти координаты используются для установки CSS-позиции.

transform: translate(x, y)

Именно такой подход обеспечивает высокую производительность анимаций.


Разделение свободного пространства

После размещения элемента необходимо обновить список свободных областей.

Предположим:

space: 400 x 400
item: 200 x 200

Элемент размещён в левом верхнем углу.

Оставшееся пространство делится на:

space_right
space_bottom
space_right:
x = space.x + item.width
y = space.y
width  = space.width - item.width
height = item.height
space_bottom:
x = space.x
y = space.y + item.height
width  = space.width
height = space.height - item.height

После этого исходная область удаляется, а новые пространства добавляются в список.


Устранение перекрывающихся областей

В процессе деления могут появляться перекрывающиеся свободные пространства. Алгоритм Packery выполняет дополнительную очистку списка областей.

Проверяется условие:

spaceA полностью содержится в spaceB

Если это так, меньшая область удаляется, поскольку она не несёт полезной информации.

Этот этап предотвращает накопление избыточных пространств и повышает эффективность размещения.


Сортировка свободных областей

Свободные пространства хранятся в массиве. Для повышения эффективности поиска они сортируются.

Наиболее распространённая стратегия сортировки:

  1. по координате Y
  2. затем по координате X

Такой порядок обеспечивает размещение элементов сверху вниз и слева направо, что соответствует естественному визуальному потоку интерфейса.


Инкрементальная перестройка макета

Одной из особенностей Packery является возможность инкрементального обновления макета.

При добавлении нового элемента:

  1. пересчитывается только необходимая часть пространства
  2. уже размещённые элементы сохраняют свои координаты
  3. выполняется локальное обновление свободных областей

Это значительно снижает вычислительную нагрузку по сравнению с полным пересчётом.


Перемещение элементов (Drag & Drop)

Алгоритм упаковки также используется при перетаскивании элементов.

Во время перемещения выполняется несколько операций:

  1. элемент временно извлекается из системы размещения
  2. пространство, которое он занимал, становится свободным
  3. алгоритм ищет новую позицию для элемента
  4. остальные элементы могут автоматически смещаться

Таким образом достигается эффект динамической перестройки макета.


Повторная упаковка (Repacking)

Иногда требуется полная переработка расположения элементов. Это происходит в следующих ситуациях:

  • изменение размеров контейнера
  • изменение размеров элементов
  • массовое добавление или удаление элементов

Процесс repack выполняется так:

  1. список свободных пространств очищается
  2. создаётся новая область размером контейнера
  3. все элементы размещаются заново

Этот процесс аналогичен первоначальной инициализации.


Влияние размеров элементов

Размеры элементов напрямую влияют на качество упаковки.

Наиболее эффективный результат достигается при:

  • кратности размеров элементов
  • ограниченном количестве различных ширин
  • предсказуемых пропорциях

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


Вертикальный и горизонтальный режим

Алгоритм Packery может работать в двух ориентациях.

Вертикальная компоновка

Элементы заполняют пространство сверху вниз.

Контейнер увеличивает высоту при необходимости.

Используется в:

  • галереях изображений
  • новостных сетках
  • карточных интерфейсах

Горизонтальная компоновка

Элементы располагаются слева направо.

Контейнер расширяется по ширине.

Применяется в:

  • горизонтальных лентах
  • панелях инструментов
  • интерактивных дашбордах

Производительность алгоритма

Сложность алгоритма зависит от:

  • количества элементов
  • числа свободных областей
  • частоты пересчёта макета

В среднем время размещения одного элемента составляет:

O(n)

где n — количество свободных пространств.

Оптимизации Packery включают:

  • удаление вложенных областей
  • сортировку пространств
  • использование CSS-трансформаций вместо абсолютных координат

Сравнение с сеточными алгоритмами

Характеристика Сеточные системы Packery
Размер элементов фиксированный произвольный
Заполнение пространства часто остаются пустоты минимальные пустоты
Перестройка макета ограниченная динамическая
Drag & Drop обычно отсутствует встроенная поддержка

Роль алгоритма в адаптивных интерфейсах

Алгоритм упаковки особенно важен в адаптивных интерфейсах.

При изменении ширины экрана:

  1. меняется ширина контейнера
  2. элементы перераспределяются
  3. свободные области пересчитываются

В результате интерфейс сохраняет плотную компоновку без жёсткой сетки.


Архитектурные компоненты алгоритма

Внутренняя архитектура Packery включает несколько ключевых модулей:

Rect

объект прямоугольника, описывающий пространство.

Packer

ядро алгоритма упаковки.

Item

объект элемента, содержащий размеры и координаты.

Layout

система управления размещением.

Эти компоненты совместно формируют механизм вычисления и обновления макета.


Пошаговый пример работы алгоритма

Пусть контейнер имеет размер:

600 x 400

Добавляются элементы:

A: 200 x 200
B: 200 x 100
C: 100 x 200
D: 300 x 100

Шаг 1

Элемент A размещается в точке:

(0,0)

Свободные области:

(200,0) 400x200
(0,200) 600x200

Шаг 2

Элемент B помещается в первую свободную область:

(200,0)

Шаг 3

Область делится и создаются новые пространства.


Шаг 4

Элемент C размещается в следующей подходящей зоне.


Шаг 5

Элемент D занимает оставшееся место.

В результате контейнер заполняется максимально плотно без заранее заданной сетки.


Практическое значение алгоритма

Алгоритм упаковки Packery используется при разработке:

  • динамических галерей изображений
  • сеток карточек контента
  • систем drag-and-drop
  • визуальных редакторов
  • панелей управления

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