Отмена операции drag

В библиотеке Muuri операция перетаскивания (drag) управляется через встроенный механизм drag-событий. Иногда возникает необходимость отменить текущую операцию перетаскивания — например, при нарушении условий перетаскивания, при недостаточном перемещении элемента или при логике интерфейса, которая запрещает перенос в определённую область.

Использование события dragStart и метода drag.cancel()

Muuri предоставляет метод cancel() у объекта drag, который позволяет прекратить текущее перетаскивание до завершения. Типичный сценарий выглядит так:

const grid = new Muuri('.grid', {
  dragEnabled: true
});

grid.on('dragStart', (item, event) => {
  // Пример условия: запрет перетаскивания, если элемент имеет класс 'fixed'
  if (item.getElement().classList.contains('fixed')) {
    item.getGrid().drag.cancel(item);
  }
});

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

  • item.getGrid() возвращает объект сетки Muuri, к которому принадлежит элемент.
  • Метод drag.cancel(item) прерывает текущее перетаскивание элемента, возвращая его на исходное место.
  • dragStart срабатывает до физического перемещения элемента, поэтому отмена здесь предотвращает любые визуальные сдвиги.

Отмена во время dragMove

Иногда нужно отменить перетаскивание уже во время движения. Для этого используется событие dragMove:

grid.on('dragMove', (item, event) => {
  const position = item.getDrag().getTranslate();
  // Отмена, если элемент пересёк запрещённую область
  if (position.left > 500) {
    item.getGrid().drag.cancel(item);
  }
});

Особенности работы:

  • item.getDrag().getTranslate() возвращает текущую координату {left, top} элемента.
  • Метод drag.cancel(item) может быть вызван многократно — Muuri корректно обработает повторные вызовы без ошибок.
  • После отмены элемент мгновенно возвращается на исходную позицию, визуальные анимации обеспечивают плавность возврата.

Влияние на другие события drag

При отмене перетаскивания Muuri срабатывают соответствующие события:

  • dragEnd — срабатывает даже при отмене. Параметр isCanceled указывает на отмену.
  • move и layoutEnd могут быть вызваны в зависимости от конфигурации сетки.

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

grid.on('dragEnd', (item) => {
  if (item.isDragging()) {
    console.log('Перетаскивание отменено');
  }
});

Программная отмена drag без пользовательского действия

Muuri позволяет отменять drag не только через события, но и через прямой вызов метода для элементов в любой момент:

const item = grid.getItems()[0];
grid.drag.cancel(item);

Это полезно для сценариев:

  • Автоматическая проверка правил после начала drag.
  • Сброс состояния сетки в результате внешних изменений.
  • Взаимодействие с другими библиотеками, которые ограничивают перемещение элементов.

Советы по использованию

  • Вызывать drag.cancel() только после dragStart, иначе элемент может быть в состоянии, когда отмена не будет корректно применена.
  • Проверять координаты или классы элемента, чтобы определить необходимость отмены.
  • Не полагаться на CSS для отмены движения, так как Muuri использует трансформации translate для анимаций и позиции элементов.

Пример комплексной логики отмены

grid.on('dragStart', (item) => {
  if (item.getElement().dataset.locked === 'true') {
    item.getGrid().drag.cancel(item);
  }
});

grid.on('dragMove', (item) => {
  const pos = item.getDrag().getTranslate();
  if (pos.top < 0 || pos.left < 0) {
    item.getGrid().drag.cancel(item);
  }
});

grid.on('dragEnd', (item) => {
  if (item.isDragging()) {
    console.log('Элемент не был перемещён');
  }
});

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

Заключение по механике

Использование drag.cancel() в сочетании с событиями dragStart, dragMove и dragEnd обеспечивает:

  • Полный контроль над перетаскиванием.
  • Предотвращение перемещения запрещённых элементов.
  • Плавное визуальное возвращение элемента на место.
  • Интеграцию логики сетки с внешними условиями интерфейса.

Методы Muuri делают отмену drag гибкой и предсказуемой, обеспечивая надёжное управление интерактивными элементами в любой сетке.