Создание экземпляра Draggable

Для начала необходимо подключить библиотеку Shopify Draggable. Она доступна через npm, Yarn или CDN. Наиболее распространённый способ — установка через npm:

npm install @shopify/draggable

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

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

Для использования через CDN можно добавить ссылку в HTML:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shopify/draggable@1.0.0-beta.8/lib/draggable.css">
<script src="https://cdn.jsdelivr.net/npm/@shopify/draggable@1.0.0-beta.8/lib/draggable.bundle.js"></script>

Создание экземпляра Draggable

Экземпляр Draggable создаётся с помощью конструктора Draggable, которому передаётся два основных параметра: контейнер и опции.

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

Разбор параметров:

  • document.querySelectorAll('.list') — контейнеры, внутри которых элементы будут перетаскиваться. Можно передавать несколько контейнеров.

  • draggable: '.list-item' — CSS-селектор элементов, которые можно перетаскивать.

  • handle: '.handle' — опциональный селектор, указывающий, какая часть элемента будет «ручкой» для перетаскивания.

  • mirror — объект настроек для зеркального отображения элемента при перетаскивании:

    • constrainDimensions — фиксирует размеры зеркала относительно исходного элемента.
    • xAxis и yAxis — можно ограничить движение по одной оси.

Основные опции

1. draggable

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

2. handle

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

3. delay

Задаёт задержку в миллисекундах перед началом перетаскивания:

delay: 100 // 0.1 секунды

4. mirror

Настройки зеркала, создаваемого при перетаскивании. Содержит:

  • constrainDimensions — фиксирует размеры зеркала.
  • xAxis и yAxis — ограничение движения по оси.
  • appendTo — контейнер, в который помещается зеркало.
  • cursorOffset — смещение зеркала относительно курсора.

5. plugins

Позволяет подключать дополнительные плагины, например Sortable или Swappable. Пример:

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

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

Методы экземпляра Draggable

1. on(event, callback)

Подписка на события, например drag:start, drag:move, drag:stop:

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

2. off(event, callback)

Отписка от событий.

3. destroy()

Удаляет экземпляр Draggable и освобождает ресурсы:

draggable.destroy();

4. enable() / disable()

Включение и отключение возможности перетаскивания.


События Draggable

События делятся на несколько категорий:

  • Drag events drag:start, drag:move, drag:stop — основные события при перетаскивании.

  • Mirror events mirror:created, mirror:destroyed — создаются и удаляются зеркала.

  • Sortable/Swappable events (при использовании плагинов) sortable:sorted, swappable:swapped — управление сортировкой или обменом элементов.

Пример подписки на несколько событий:

draggable
  .on('drag:start', event => console.log('start', event))
  .on('drag:stop', event => console.log('stop', event))
  .on('mirror:created', event => console.log('mirror created', event));

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

Можно ограничить движение элементов:

const draggable = new Draggable(document.querySelectorAll('.list'), {
  draggable: '.list-item',
  mirror: {
    constrainDimensions: true,
    xAxis: true, // движение только по X
  },
});

Для ограничения в пределах контейнера используется CSS-свойство overflow или дополнительные вычисления позиции внутри события drag:move.


Интеграция с динамическими элементами

Если элементы добавляются динамически, экземпляр Draggable не будет автоматически их обрабатывать. Необходимо пересоздавать Draggable или использовать метод destroy() и заново инициализировать:

draggable.destroy();

draggable = new Draggable(document.querySelectorAll('.list'), {
  draggable: '.list-item',
});

Альтернатива — создавать отдельный контейнер для новых элементов и инициализировать Draggable на нём.


Пример полной конфигурации

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

const draggable = new Draggable(document.querySelectorAll('.list'), {
  draggable: '.list-item',
  handle: '.handle',
  delay: 100,
  mirror: {
    constrainDimensions: true,
    appendTo: document.body,
    cursorOffset: { x: 10, y: 10 },
  },
  plugins: [Sortable],
});

draggable.on('drag:start', event => console.log('drag start', event))
         .on('drag:stop', event => console.log('drag stop', event))
         .on('mirror:created', event => console.log('mirror created', event));

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


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

  • Использовать конкретные селекторы для контейнера и draggable элементов, избегая * или слишком общих селекторов.
  • Отключать Draggable на неактивных контейнерах через disable() для уменьшения нагрузки.
  • Для длинных списков оптимизировать обработку событий drag:move, минимизируя DOM-операции внутри callback.

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