Обработка обмена элементами

Библиотека Shopify Draggable предоставляет мощный механизм для работы с перетаскиванием элементов, включая возможность обмена их местами. Обмен элементами (swap) часто используется в интерфейсах, где важен порядок элементов, например, списках товаров, карточках задач или интерактивных таблицах.

Настройка Draggable для обмена

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

import { Swappable } from '@shopify/draggable';

const container = document.querySelector('.draggable-container');
const swappable = new Swappable(container, {
  draggable: '.draggable-item',
  swapAnimation: {
    duration: 300,
    easingFunction: 'ease-in-out'
  }
});
  • draggable — селектор элементов, которые можно перемещать.

  • swapAnimation — объект с настройками анимации обмена:

    • duration — длительность анимации в миллисекундах.
    • easingFunction — тип функции сглаживания движения.

События обмена

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

  • swappable:start — срабатывает при начале перетаскивания элемента.
  • swappable:swapped — вызывается после успешного обмена элементов. Передает объект с информацией о замененных элементах:
swappable.on('swappable:swapped', (event) => {
  console.log(event.dragEvent.data.originalSource); // Перетаскиваемый элемент
  console.log(event.dragEvent.data.over); // Элемент, с которым произошел swap
});
  • swappable:stop — срабатывает после завершения перетаскивания, независимо от того, был ли обмен.

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

Опции конфигурации

Swappable поддерживает следующие ключевые опции:

  • draggable — CSS-селектор элементов для перетаскивания.
  • handle — необязательный селектор, указывающий конкретную область, за которую можно захватывать элемент.
  • swapAnimation — объект для настройки анимации.
  • mirror — объект конфигурации зеркала (mirror: { constrainDimensions: true }) для точного отображения перетаскиваемого элемента.
  • ignoreInputTextSelection — булевое значение, предотвращающее случайные обмены при выделении текста.

Пример расширенной конфигурации:

const swappable = new Swappable(container, {
  draggable: '.draggable-item',
  handle: '.drag-handle',
  swapAnimation: {
    duration: 250,
    easingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)'
  },
  mirror: {
    constrainDimensions: true
  },
  ignoreInputTextSelection: true
});

Взаимодействие с DOM и сохранение порядка

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

let items = Array.from(document.querySelectorAll('.draggable-item'));

swappable.on('swappable:swapped', (event) => {
  const sourceIndex = items.indexOf(event.dragEvent.data.originalSource);
  const overIndex = items.indexOf(event.dragEvent.data.over);

  [items[sourceIndex], items[overIndex]] = [items[overIndex], items[sourceIndex]];

  console.log('Новый порядок элементов:', items.map(el => el.textContent));
});

Такой подход позволяет интегрировать Draggable с Vue, React или любым другим фреймворком, где важен порядок элементов.

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

Анимация играет ключевую роль в восприятии интерфейса. Shopify Draggable использует CSS-переходы для swap, что обеспечивает плавность даже при большом количестве элементов. Основные рекомендации:

  • Ограничивать длительность анимации до 300–400 мс.
  • Использовать transform: translate3d() для GPU-ускорения.
  • Выключать анимацию при больших списках для повышения производительности.

Продвинутые сценарии

  1. Обмен между контейнерами: Swappable поддерживает обмен элементов между разными контейнерами. Для этого достаточно передать массив контейнеров:
const swappable = new Swappable([containerA, containerB], {
  draggable: '.draggable-item'
});
  1. Фильтрация элементов: можно исключить определенные элементы из обмена с помощью CSS-классов и селектора draggable.

  2. Интеграция с сервером: при событии swappable:swapped можно отправлять AJAX-запрос для обновления порядка элементов в базе данных.

Частые ошибки и нюансы

  • Элемент вне контейнера — Swappable корректно работает только с элементами внутри одного или нескольких указанных контейнеров.
  • Несовпадение селекторов — если draggable не совпадает с классами элементов, обмен не сработает.
  • Конфликт с другими библиотеками drag-and-drop — рекомендуется отключать сторонние обработчики событий mousedown и touchstart.
  • Проблемы с зеркалом (mirror) — для корректного отображения зеркала элемент должен иметь явно заданные размеры.

Примеры визуального обмена

  • Перетаскивание карточек задач в канбан-доске.
  • Изменение порядка товаров в списке корзины.
  • Редактирование последовательности слайдов в галерее.

Библиотека Shopify Draggable с модулем Swappable обеспечивает высокую гибкость при работе с интерактивными интерфейсами, позволяя легко реализовывать обмен элементов с анимацией и полным контролем над событиями и состоянием DOM.