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

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


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

В Draggable область, в которой элемент может перемещаться, задаётся через параметр containers. Это массив DOM-элементов или селекторов, внутри которых разрешено перетаскивание.

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

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

const container = document.querySelector('.list');

const draggable = new Draggable(container, {
  draggable: '.item',
  containers: [container] // Перетаскивание ограничено этим контейнером
});

В этом примере элемент с классом .item можно перемещать только внутри .list. Любая попытка выйти за пределы контейнера будет автоматически блокироваться библиотекой.


Ограничение по осям: axis

Draggable поддерживает ограничение движения по горизонтали или вертикали с помощью опции axis.

  • 'x' – только горизонтальное перемещение
  • 'y' – только вертикальное перемещение

Пример:

const draggable = new Draggable(container, {
  draggable: '.item',
  axis: 'y' // Перемещение только по вертикали
});

Такой подход полезен для списков, где нужно ограничить движение элементов только вверх и вниз.


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

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

draggable.on('drag:move', (event) => {
  const bounds = event.source.parentElement.getBoundingClientRect();
  const x = event.sensor.clientX;
  const y = event.sensor.clientY;

  // Ограничение по координатам контейнера
  if (x < bounds.left) event.sensor.clientX = bounds.left;
  if (x > bounds.right) event.sensor.clientX = bounds.right;
  if (y < bounds.top) event.sensor.clientY = bounds.top;
  if (y > bounds.bottom) event.sensor.clientY = bounds.bottom;
});

Использование таких проверок позволяет реализовать точный контроль над тем, где элемент может появляться, независимо от структуры DOM.


Ограничение для нескольких контейнеров

Draggable позволяет задавать несколько контейнеров для перемещения элементов между ними. При этом перемещение в другие области будет разрешено только внутри перечисленных контейнеров:

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

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


Плавающие элементы и mirror

При включении mirror создаётся копия перетаскиваемого элемента. Ограничение области действует и для зеркала:

const draggable = new Draggable(container, {
  draggable: '.item',
  mirror: {
    constrainDimensions: true // Зеркало ограничено размерами оригинального элемента
  }
});

Можно дополнительно использовать событие mirror:move для контроля положения зеркала и предотвращения выхода за пределы контейнера.


Практические советы

  • Для списков и таблиц лучше использовать axis: 'y' и containers, чтобы элементы не пересекали соседние блоки.
  • При динамическом изменении размеров контейнера нужно пересчитывать границы в drag:move, чтобы ограничения оставались актуальными.
  • Ограничение можно комбинировать: одновременно ограничивать по контейнеру и по оси движения для более строгого контроля.
  • Проверка положения элемента через getBoundingClientRect() позволяет учесть любые внешние отступы, скролл и трансформации.

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