Синхронизация нескольких экземпляров

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


Инициализация нескольких экземпляров

Для начала создаются независимые экземпляры Isotope для каждого контейнера:

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

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

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


Синхронизация фильтров

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

var filters = document.querySelectorAll('.filter-button');

filters.forEach(function(button) {
  button.addEventListener('click', function() {
    var filterValue = button.getAttribute('data-filter');

    grid1.arrange({ filter: filterValue });
    grid2.arrange({ filter: filterValue });
  });
});

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


Синхронизация сортировки

SortBy и sortAscending можно синхронизировать аналогичным образом. Например:

var sortButtons = document.querySelectorAll('.sort-button');

sortButtons.forEach(function(button) {
  button.addEventListener('click', function() {
    var sortByValue = button.getAttribute('data-sort-by');

    grid1.arrange({ sortBy: sortByValue });
    grid2.arrange({ sortBy: sortByValue });
  });
});

Важно использовать одинаковые параметры сортировки для всех экземпляров, чтобы порядок элементов оставался консистентным.


События для синхронизации состояния

Isotope поддерживает множество событий: arrangeComplete, layoutComplete, removeComplete. Они позволяют отслеживать изменения в одном экземпляре и применять их к другим. Пример синхронизации после завершения анимации:

grid1.on('arrangeComplete', function(filteredItems) {
  var currentFilter = grid1.options.filter;
  grid2.arrange({ filter: currentFilter });
});

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


Оптимизация производительности

При работе с большими коллекциями элементов синхронизация нескольких экземпляров может создать нагрузку. Рекомендуется:

  • Использовать requestAnimationFrame при массовых обновлениях;
  • Группировать события, чтобы избежать многократного вызова arrange;
  • Ограничивать количество одновременно синхронизируемых экземпляров до необходимого минимума.

Пример использования requestAnimationFrame для синхронизации фильтров:

filters.forEach(function(button) {
  button.addEventListener('click', function() {
    var filterValue = button.getAttribute('data-filter');

    window.requestAnimationFrame(function() {
      grid1.arrange({ filter: filterValue });
      grid2.arrange({ filter: filterValue });
    });
  });
});

Синхронизация через кастомные события

Можно создать централизованный механизм событий для всех экземпляров. Это упрощает поддержку и расширяемость:

function syncIsotope(eventType, options) {
  [grid1, grid2, grid3].forEach(function(grid) {
    grid.arrange(options);
    grid.emitEvent(eventType, [options]);
  });
}

document.querySelectorAll('.filter-button').forEach(function(button) {
  button.addEventListener('click', function() {
    var filterValue = button.getAttribute('data-filter');
    syncIsotope('filterChanged', { filter: filterValue });
  });
});

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


Управление разной структурой элементов

Если экземпляры содержат разные элементы или их количество различается, синхронизация фильтров и сортировки всё равно возможна. Для этого важно:

  • Использовать одинаковые классы и атрибуты для фильтруемых элементов;
  • Проверять наличие элементов перед применением фильтра:
if (grid2.getItemElements().length > 0) {
  grid2.arrange({ filter: filterValue });
}

Эта проверка предотвращает ошибки и лишние вызовы arrange.


Анимация и визуальная согласованность

Для синхронизированных экземпляров рекомендуется устанавливать одинаковые параметры анимации: transitionDuration и stagger. Это позволяет избежать визуальных «разрывов» между сетками:

var gridOptions = {
  itemSelector: '.grid-item',
  layoutMode: 'masonry',
  transitionDuration: '0.4s',
  stagger: 30
};

var grid1 = new Isotope('#grid1', gridOptions);
var grid2 = new Isotope('#grid2', gridOptions);

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