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

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


Использование события drag:start для контроля начала перетаскивания

Shopify Draggable позволяет перехватывать момент начала перетаскивания с помощью события drag:start. Это событие передаёт объект события с информацией о целевом элементе и контейнере.

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

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

draggable.on('drag:start', (event) => {
  const element = event.source;
  
  // Условие для отмены перетаскивания
  if (element.dataset.locked === 'true') {
    event.cancel();
  }
});

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

  • event.source — элемент, который пытаются перетащить.
  • event.cancel() — метод, который полностью отменяет действие drag.
  • Можно использовать атрибуты или классы для определения, какие элементы недоступны для перетаскивания.

Временная отмена при drag:move

Иногда необходимо разрешить перетаскивание, но предотвратить перемещение за пределы допустимой зоны. Событие drag:move позволяет контролировать текущую позицию элемента и, при необходимости, останавливать перетаскивание.

draggable.on('drag:move', (event) => {
  const currentX = event.sensorEvent.clientX;
  const currentY = event.sensorEvent.clientY;
  
  // Запретить движение за пределы контейнера
  const container = event.source.parentElement.getBoundingClientRect();
  if (currentX < container.left || currentX > container.right ||
      currentY < container.top || currentY > container.bottom) {
    event.cancel();
  }
});

Примечание: Отмена drag:move предотвращает дальнейшее перемещение элемента, но не завершает сам drag, поэтому после возвращения в допустимую область перетаскивание продолжится.


Возврат элемента на исходное место с drag:stop

Если требуется вернуть элемент в исходное положение после завершения drag (например, если пользователь отпустил элемент вне разрешённой зоны), событие drag:stop предоставляет необходимую информацию:

draggable.on('drag:stop', (event) => {
  const element = event.source;
  const originalParent = element.dataset.originalParent;
  
  if (!event.overContainer || event.overContainer.dataset.reject === 'true') {
    // Возврат в исходное положение
    element.style.transform = '';
    originalParent.appendChild(element);
  }
});

Советы по реализации возврата:

  • Сохранять исходный контейнер и позицию элемента при drag:start.
  • Использовать CSS transform или абсолютное позиционирование для плавного возврата.
  • Можно интегрировать анимацию с помощью transition для визуального эффекта возврата.

Программная отмена перетаскивания

Draggable позволяет инициировать отмену drag программно, не дожидаясь событий мыши:

draggable.cancel(); // Отменяет текущее перетаскивание

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


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

Для контроля, где элемент может быть перетащен, используются containers и опции droppable. В комбинации с отменой drag можно реализовать строгие правила перемещения:

const droppable = new Draggable(document.querySelectorAll('.draggable-container'), {
  draggable: '.draggable-item',
  delay: 100, // предотвращение случайных drag
});

droppable.on('droppable:over', (event) => {
  if (event.over.dataset.reject === 'true') {
    event.cancel(); // запрещает "высадку" элемента
  }
});

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

  • droppable:over и droppable:out помогают контролировать, где элемент можно оставить.
  • Отмена здесь предотвращает завершение drop, но не остановит drag до момента отпускания мыши.

Практическое применение

Отмена перетаскивания необходима в следующих случаях:

  1. Защита фиксированных элементов – элементы, которые нельзя перемещать.
  2. Ограничение зон перемещения – нельзя перемещать элементы за пределы контейнера.
  3. Валидация действия перед drop – проверка условий перед фактическим перемещением.
  4. Плавный возврат – предотвращение разрыва пользовательского опыта при недопустимых действиях.

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