layoutComplete

Событие layoutComplete относится к системе событий библиотеки Masonry и сигнализирует о завершении процесса размещения элементов внутри контейнера. Оно вызывается после того, как библиотека полностью рассчитала позиции всех элементов сетки и применила соответствующие стили позиционирования.

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


Когда возникает layoutComplete

Событие срабатывает после завершения метода layout. Этот метод отвечает за вычисление координат каждого элемента и их размещение в колонках с учётом высоты предыдущих элементов.

layoutComplete вызывается в нескольких случаях:

  • после первоначальной инициализации Masonry;
  • после явного вызова layout();
  • после операций добавления элементов;
  • после операций удаления элементов;
  • после изменения размеров контейнера;
  • после перерасчёта позиций элементов.

Событие гарантирует, что:

  • все элементы уже получили координаты top и left;
  • CSS-позиционирование полностью применено;
  • браузер завершил перерасчёт макета.

Подписка на событие

Masonry использует систему событий, основанную на механизме EvEmitter. Подписка выполняется через метод on.

var grid = document.querySelector('.grid');

var msnry = new Masonry(grid, {
  itemSelector: '.grid-item',
  columnWidth: 200
});

msnry.on('layoutComplete', function(items) {
  console.log('Layout завершён');
});

Функция обработчика получает массив элементов, которые участвовали в последнем процессе компоновки.


Аргументы обработчика

Обработчик layoutComplete принимает один аргумент:

Аргумент Тип Описание
items Array массив объектов элементов Masonry

Каждый объект массива представляет собой внутреннюю структуру Item, используемую Masonry.

Пример использования:

msnry.on('layoutComplete', function(items) {
  console.log('Количество элементов:', items.length);
});

Объект элемента Item

Каждый объект Item содержит информацию о DOM-элементе и его текущем положении.

Основные свойства:

Свойство Описание
element DOM-элемент
position.x координата по горизонтали
position.y координата по вертикали
size размеры элемента

Пример доступа:

msnry.on('layoutComplete', function(items) {
  items.forEach(function(item) {
    console.log(item.position.x, item.position.y);
  });
});

Это позволяет выполнять дополнительную логику, зависящую от координат элементов.


Последовательность работы события

Внутренний цикл работы Masonry при вызове layout() выглядит следующим образом:

  1. сбор всех элементов сетки;
  2. вычисление ширины колонок;
  3. расчёт высоты каждой колонки;
  4. определение позиции каждого элемента;
  5. применение CSS-позиционирования;
  6. обновление внутренних структур данных;
  7. вызов события layoutComplete.

Таким образом, обработчик всегда получает окончательный результат компоновки.


Использование после загрузки изображений

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

Для этого обычно используется библиотека imagesLoaded.

Пример:

var grid = document.querySelector('.grid');

var msnry = new Masonry(grid, {
  itemSelector: '.grid-item',
  columnWidth: 200
});

imagesLoaded(grid, function() {
  msnry.layout();
});

msnry.on('layoutComplete', function(items) {
  console.log('Layout после загрузки изображений завершён');
});

В этом сценарии layoutComplete выполняется только после корректного вычисления размеров всех элементов.


Использование при динамическом добавлении элементов

Когда новые элементы добавляются в сетку, Masonry может перерассчитать расположение. После этого снова вызывается layoutComplete.

Пример:

var newItems = document.querySelectorAll('.new-item');

msnry.appended(newItems);

msnry.on('layoutComplete', function(items) {
  console.log('Перерасчёт после добавления элементов завершён');
});

Последовательность операций:

  1. добавление элементов в DOM;
  2. регистрация их в Masonry;
  3. пересчёт позиций;
  4. вызов layoutComplete.

Использование для запуска анимаций

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

Пример:

msnry.on('layoutComplete', function(items) {
  items.forEach(function(item) {
    item.element.classList.add('visible');
  });
});

CSS:

.grid-item {
  opacity: 0;
  transition: opacity 0.5s;
}

.grid-item.visible {
  opacity: 1;
}

Анимация начнётся только после того, как элементы займут свои позиции.


Отписка от события

Для удаления обработчика используется метод off.

function onLayout(items) {
  console.log('Layout завершён');
}

msnry.on('layoutComplete', onLayout);

msnry.off('layoutComplete', onLayout);

Это важно при создании сложных интерфейсов, где компоненты могут уничтожаться или пересоздаваться.


Разница между layoutComplete и arrangeComplete

В библиотеке Masonry существуют похожие события, выполняющие разные функции.

Событие Назначение
layoutComplete завершение расчёта позиций
arrangeComplete завершение операций фильтрации и сортировки

layoutComplete отвечает исключительно за геометрию размещения элементов.


Работа при ресайзе окна

Если включена опция:

resize: true

Masonry автоматически пересчитывает layout при изменении размеров окна браузера. После каждого перерасчёта снова срабатывает layoutComplete.

Пример:

msnry.on('layoutComplete', function() {
  console.log('Layout обновился после resize');
});

Использование для отладки

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

Пример:

msnry.on('layoutComplete', function(items) {
  console.table(items.map(function(item) {
    return {
      x: item.position.x,
      y: item.position.y
    };
  }));
});

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


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

Частые срабатывания layoutComplete могут влиять на производительность, особенно если обработчик выполняет тяжёлые операции.

Рекомендации:

  • избегать сложных вычислений внутри обработчика;
  • не выполнять повторный layout() внутри layoutComplete;
  • использовать debounce при обработке resize.

Пример debounce:

let timer;

msnry.on('layoutComplete', function() {
  clearTimeout(timer);
  
  timer = setTimeout(function() {
    console.log('Оптимизированная обработка');
  }, 100);
});

Внутренняя реализация события

Внутри Masonry после завершения layout вызывается метод эмиттера:

this.dispatchEvent('layoutComplete', null, [items]);

Этот механизм обеспечивает:

  • передачу массива элементов;
  • синхронный вызов всех подписчиков;
  • возможность регистрации нескольких обработчиков.

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