Множественные drop-зоны

Библиотека Shopify Draggable предоставляет мощные инструменты для организации интерактивных drag-and-drop интерфейсов. Работа с множественными drop-зонами является ключевым элементом при создании сложных интерфейсов, где один элемент может быть перемещён в различные контейнеры, и каждый из них должен иметь собственную логику обработки событий.

В Draggable каждая drop-зона представляет собой отдельный Droppable объект, который может быть связан с одним или несколькими контейнерами. Для множественных drop-зон важно понимать, что события drag:start, drag:over, drag:enter, drag:leave и drag:stop срабатывают отдельно для каждого контейнера, что позволяет реализовать тонкую настройку поведения элементов при их перемещении.

import { Draggable, Droppable } from '@shopify/draggable';

const containers = document.querySelectorAll('.container');
const droppables = document.querySelectorAll('.droppable');

const draggable = new Draggable(containers, {
  draggable: '.item',
  delay: 0,
});

const droppable = new Droppable(droppables, {
  draggable: '.item',
});

Настройка множественных drop-зон

Для работы с множественными drop-зонами важно различать два основных подхода:

  1. Общий droppable для всех зон – создаётся один объект Droppable, который принимает все контейнеры. Такой подход удобен для простой логики, когда все drop-зоны имеют одинаковое поведение.
const droppable = new Droppable(document.querySelectorAll('.drop-zone'), {
  draggable: '.item'
});
  1. Индивидуальный droppable для каждой зоны – создаётся несколько экземпляров Droppable, по одному для каждого контейнера. Это позволяет задавать уникальные настройки и события для каждой зоны.
document.querySelectorAll('.drop-zone').forEach(zone => {
  new Droppable(zone, { draggable: '.item' });
});

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

Управление событиями drag и drop

Множественные drop-зоны требуют особого внимания к событиям, так как один и тот же элемент может одновременно входить в область нескольких зон. Основные события:

  • drag:start – срабатывает при начале перетаскивания любого элемента.
  • drag:over – активируется, когда элемент наведен над drop-зоной.
  • drag:enter – срабатывает при входе элемента в drop-зону.
  • drag:leave – фиксирует момент выхода элемента из зоны.
  • drag:stop – завершает перетаскивание и позволяет обработать финальное положение элемента.

Пример использования событий для множественных зон:

droppable.on('drag:enter', (event) => {
  event.dropZone.classList.add('highlight');
});

droppable.on('drag:leave', (event) => {
  event.dropZone.classList.remove('highlight');
});

droppable.on('drag:stop', (event) => {
  if (event.dropZone) {
    event.dropZone.appendChild(event.source);
  }
});

Сортировка и ограничение drop-зон

Draggable позволяет задавать приоритеты drop-зон и управлять сортировкой элементов. Например, можно ограничить перетаскивание только в определённые контейнеры или запретить перемещение элементов в пустую drop-зону.

droppable.on('drag:stop', (event) => {
  const allowedZones = ['.zone-a', '.zone-b'];
  if (!allowedZones.includes(event.dropZone.className)) {
    event.source.parentNode.appendChild(event.source);
  }
});

Также важно учитывать позиционирование внутри зоны. Можно задавать правила вставки элемента перед или после определённых дочерних элементов с помощью методов:

  • event.dropZone.insertBefore(source, referenceElement)
  • event.dropZone.appendChild(source)

Визуальные эффекты и подсветка

Для улучшения UX при работе с множественными drop-зонами часто используют визуальные подсказки:

  • Подсветка зоны при наведении (drag:enter / drag:over)
  • Эффект возврата при неправильном drop (drag:stop)
  • Анимация перемещения через CSS-переходы или библиотеку SortableAnimation от Draggable
.drop-zone.highlight {
  border: 2px dashed #007bff;
  background-color: rgba(0, 123, 255, 0.1);
}
droppable.on('drag:enter', (event) => {
  event.dropZone.classList.add('highlight');
});

droppable.on('drag:leave', (event) => {
  event.dropZone.classList.remove('highlight');
});

Передача данных между зонами

Множественные drop-зоны часто используются для перемещения данных между различными контейнерами. Для этого можно использовать свойства события event.source (перетаскиваемый элемент) и event.dropZone (целевой контейнер). Дополнительно можно хранить данные через dataset элементов:

droppable.on('drag:stop', (event) => {
  const itemData = event.source.dataset.id;
  const targetZone = event.dropZone.dataset.zone;

  console.log(`Элемент ${itemData} перемещен в зону ${targetZone}`);
});

Особенности интеграции с динамическим контентом

Если контейнеры создаются динамически, необходимо инициализировать Droppable после добавления элементов в DOM. Для динамических интерфейсов рекомендуется использовать метод destroy() перед повторной инициализацией, чтобы избежать дублирования событий.

droppable.destroy();
new Droppable(document.querySelectorAll('.drop-zone'), { draggable: '.item' });

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

  • Ограничивать количество элементов в drag-зоне при большом объёме данных.
  • Использовать CSS-анимации вместо JavaScript для плавного перемещения.
  • Объединять обработчики событий для нескольких drop-зон, если логика повторяется, чтобы уменьшить количество слушателей.

Множественные drop-зоны в Shopify Draggable позволяют создавать высокоинтерактивные интерфейсы с гибкой логикой перетаскивания, точной сортировкой и визуальной обратной связью, обеспечивая профессиональный уровень UX в веб-приложениях.