Жизненный цикл перетаскивания

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


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

Для начала работы с Draggable создается экземпляр класса Draggable, которому передаются:

  • контейнеры (containers) — элементы DOM, внутри которых разрешено перетаскивание;
  • селектора элементов (draggable) — конкретные элементы, которые можно перемещать.
import { Draggable } from '@shopify/draggable';

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

На этом этапе библиотека подготавливает внутренние структуры для отслеживания состояния каждого перетаскиваемого элемента и контейнера.


События жизненного цикла

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

1. drag:start

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

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

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

  • event.source — исходный элемент, который пользователь начал перемещать.
  • В это время можно добавлять CSS-классы, изменять стили или инициировать анимации.

2. drag:move

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

draggable.on('drag:move', (event) => {
  console.log('Перемещение элемента', event.source, 'координаты', event.sensorEvent.clientX, event.sensorEvent.clientY);
});

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

  • Доступны реальные координаты курсора через event.sensorEvent.
  • Можно реализовывать интерактивные подсказки или ограничивать движение по определенной оси.

3. drag:over и drag:out

Эти события связаны с контейнерами. drag:over срабатывает при наведении перетаскиваемого элемента на новый контейнер, а drag:out — при выходе из него.

draggable.on('drag:over', (event) => {
  console.log('Элемент над контейнером', event.overContainer);
});

draggable.on('drag:out', (event) => {
  console.log('Элемент покинул контейнер', event.overContainer);
});

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

  • Позволяет изменять стили контейнера при наведении, подсвечивать возможные позиции для вставки.
  • Поддерживает drag-and-drop между разными контейнерами.

4. drag:stop

Срабатывает в момент завершения перетаскивания. На этом этапе происходит:

  • сброс временных стилей и классов;
  • фиксация нового положения элемента;
  • вызов любых пользовательских обработчиков для окончательной логики.
draggable.on('drag:stop', (event) => {
  console.log('Перетаскивание завершено', event.source);
});

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

  • event.source — элемент, завершивший перемещение.
  • Можно инициировать анимацию возврата элемента, если он не был перемещен в допустимую область.

Вспомогательные события

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

  • sortable:swap — возникает при обмене двух элементов внутри сортируемого списка;
  • sortable:sorted — фиксирует финальный порядок элементов после перетаскивания;
  • drag:mirror:create и drag:mirror:destroy — создаются и удаляются зеркала элементов, используемые для визуальной анимации перетаскивания.
draggable.on('drag:mirror:create', (event) => {
  event.mirror.style.background = 'rgba(0, 0, 0, 0.1)';
});

Особенности зеркал:

  • Отделяют визуальное отображение перемещаемого элемента от реального DOM, что позволяет сохранять исходный макет страницы без изменений до завершения операции.
  • Позволяют создавать плавные анимации и эффект «плавающего» элемента.

Управление состоянием и отмена перетаскивания

Важной частью жизненного цикла является возможность отмены перетаскивания. Для этого можно вызвать метод cancel() на событии drag:start или drag:move, чтобы предотвратить перемещение элемента.

draggable.on('drag:start', (event) => {
  if (event.source.classList.contains('fixed')) {
    event.cancel();
  }
});

Применение:

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

Итоги управления жизненным циклом

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

  1. Инициализация — подготовка контейнеров и элементов.
  2. Начало перетаскивания (drag:start) — фиксация исходного состояния.
  3. Перемещение (drag:move) — отслеживание позиции и обновление интерфейса.
  4. Взаимодействие с контейнерами (drag:over, drag:out) — управление возможными зонами размещения.
  5. Завершение (drag:stop) — финальная фиксация положения, очистка стилей.
  6. Дополнительные события — зеркала, сортировка и обмен элементов.
  7. Отмена/блокировка — управление исключениями и правилами перемещения.

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