Композиция возможностей

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

Ключевые компоненты библиотеки:

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

Инициализация Draggable

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

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

const draggable = new Draggable(document.querySelectorAll('.draggable-container'), {
  draggable: '.draggable-item',
  delay: 0,
  mirror: {
    constrainDimensions: true
  }
});

Ключевые моменты:

  • document.querySelectorAll('.draggable-container') — контейнер, внутри которого находятся перетаскиваемые элементы.
  • draggable: '.draggable-item' — селектор элементов, которые будут перетаскиваться.
  • delay — задержка перед началом перетаскивания, полезна для предотвращения случайных срабатываний.
  • mirror — объект настроек зеркального отображения: constrainDimensions ограничивает размеры зеркала исходными размерами элемента.

Использование плагинов

Draggable позволяет подключать плагины для расширения возможностей:

1. Sortable

Позволяет изменять порядок элементов внутри контейнера.

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

const sortable = new Sortable(document.querySelectorAll('.sortable-container'), {
  draggable: '.sortable-item',
  delay: 100
});

Особенности:

  • Плагин автоматически отслеживает позиции элементов.
  • Поддерживает событие sortable:stop, позволяющее реагировать на завершение перемещения.
  • Можно комбинировать с другими плагинами, например Swappable для обмена элементов.

2. Swappable

Обеспечивает возможность обмена местами элементов при перетаскивании:

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

const swappable = new Swappable(document.querySelectorAll('.swappable-container'), {
  draggable: '.swappable-item',
  delay: 50
});

События Swappable:

  • swappable:start — начало перетаскивания.
  • swappable:swapped — элементы успешно обменялись местами.
  • swappable:stop — завершение операции.

3. Plugins Mirror

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

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

const draggableWithMirror = new Draggable(document.querySelectorAll('.mirror-container'), {
  draggable: '.mirror-item',
  mirror: {
    appendTo: 'body',
    constrainDimensions: true
  },
  plugins: [Mirror]
});

Ключевые параметры:

  • appendTo — указывает, куда добавлять зеркальный элемент в DOM.
  • constrainDimensions — сохраняет размеры оригинала.
  • Позволяет комбинировать с другими плагинами: Sortable, Swappable.

События и их обработка

Draggable предоставляет гибкую систему событий:

Событие Описание
drag:start Начало перетаскивания элемента
drag:move Элемент перемещается, можно обновлять интерфейс
drag:stop Перетаскивание завершено
mirror:created Зеркальный элемент создан
sortable:sorted Элемент отсортирован внутри контейнера
swappable:swapped Произошел обмен элементов

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

draggable.on('drag:start', (evt) => {
  console.log('Начало перетаскивания:', evt.source);
});

draggable.on('drag:stop', (evt) => {
  console.log('Перетаскивание завершено');
});

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


Совмещение нескольких плагинов

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

const draggable = new Draggable(document.querySelectorAll('.complex-container'), {
  draggable: '.complex-item',
  plugins: [Sortable, Mirror]
});

Это даёт возможность:

  • Реализовать drag-and-drop с анимацией.
  • Сохранять визуальный эффект перетаскивания.
  • Обрабатывать события сортировки и зеркала независимо.

Пользовательские расширения

Можно создавать собственные плагины, наследуя базовый функционал Draggable:

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

class HighlightPlugin extends AbstractPlugin {
  attach() {
    this.draggable.on('drag:start', this.onStart);
  }

  detach() {
    this.draggable.off('drag:start', this.onStart);
  }

  onStart(evt) {
    evt.source.style.border = '2px solid red';
  }
}

Особенности кастомных плагинов:

  • Наследование от AbstractPlugin обеспечивает доступ к объекту Draggable и его событиям.
  • Методы attach и detach управляют подключением и отключением плагина.
  • Позволяет добавлять любые визуальные или логические эффекты на этапе перетаскивания.

Ограничение зон перетаскивания

Draggable поддерживает селекцию контейнеров и зон, куда можно перемещать элементы:

const draggable = new Draggable(document.querySelectorAll('.container'), {
  draggable: '.item',
  delay: 50,
  draggableClass: 'is-dragging'
});

draggable.on('drag:move', (evt) => {
  const allowedZones = document.querySelectorAll('.drop-zone');
  if (!Array.from(allowedZones).some(zone => zone.contains(evt.sensorEvent.target))) {
    evt.cancel();
  }
});

Преимущества такого подхода:

  • Гибкая настройка допустимых зон перемещения.
  • Возможность динамически включать/отключать зоны.
  • Лёгкая интеграция с визуальными подсказками.

Настройка зеркала и анимаций

Зеркальный элемент (mirror) может быть кастомизирован для сложных интерфейсов:

  • xAxis и yAxis — ограничение движения по оси.
  • scale — масштаб зеркала при перетаскивании.
  • CSS-анимации можно комбинировать с событиями mirror:created и drag:stop для плавного возврата элемента.

Пример с масштабированием:

draggable.on('mirror:created', (evt) => {
  evt.mirror.style.transform = 'scale(1.1)';
});

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