Ограничение области перемещения

В библиотеке Interact.js для управления интерактивными элементами широко используется возможность ограничивать область перемещения (drag constraints). Это позволяет задавать границы, в которых элемент может перемещаться, предотвращая выход за пределы контейнера или заданной области. Ограничения могут применяться как к конкретным координатам, так и к прямоугольной или произвольной области.

Настройка ограничений через restrict

Метод draggable поддерживает модификатор restrict, который позволяет определять правила ограничения. Синтаксис:

interact('.draggable')
  .draggable({
    modifiers: [
      interact.modifiers.restrict({
        restriction: 'parent',
        endOnly: true,
        elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
      })
    ],
    listeners: {
      move (event) {
        event.target.style.transform =
          `translate(${event.pageX}px, ${event.pageY}px)`;
      }
    }
  });

Пояснения к ключевым параметрам:

  • restriction – область, в пределах которой элемент может перемещаться. Может быть:

    • 'parent' — ограничение рамками родительского элемента.
    • DOM-элемент — конкретный элемент.
    • Объект с координатами { top, left, bottom, right } — точные числовые границы.
  • endOnly – если true, ограничение применяется только в момент завершения перемещения, иначе — на протяжении всего drag-события.

  • elementRect – объект, определяющий, какая часть элемента учитывается при ограничении. Поля принимают значения от 0 до 1 и соответствуют доле ширины и высоты элемента.

Ограничение по координатам

Для точного контроля можно задавать ограничения в виде объекта с координатами:

interact('.draggable')
  .draggable({
    modifiers: [
      interact.modifiers.restrict({
        restriction: { top: 50, left: 100, bottom: 400, right: 600 },
        endOnly: false
      })
    ]
  });

В этом примере элемент не сможет выйти за прямоугольник с верхней границей 50px, левой — 100px, нижней — 400px, правой — 600px.

Ограничение по родителю

Наиболее часто используемый вариант — ограничение перемещения рамками родительского контейнера. Для этого достаточно указать restriction: 'parent'. При этом elementRect позволяет контролировать, какая часть элемента не должна пересекать границы родителя:

interact('.draggable')
  .draggable({
    modifiers: [
      interact.modifiers.restrict({
        restriction: 'parent',
        elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
      })
    ]
  });
  • Значение elementRect: { top: 0, left: 0, bottom: 1, right: 1 } означает, что учитывается весь элемент при ограничении.
  • Если задать bottom: 0.5, нижняя граница элемента может выйти за пределы родителя на половину своей высоты.

Ограничение с кастомной функцией

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

interact('.draggable')
  .draggable({
    modifiers: [
      interact.modifiers.restrict({
        restriction: function (x, y, element) {
          const maxX = window.innerWidth - element.offsetWidth;
          const maxY = window.innerHeight - element.offsetHeight;
          return {
            x: Math.min(Math.max(x, 0), maxX),
            y: Math.min(Math.max(y, 0), maxY)
          };
        },
        endOnly: false
      })
    ]
  });

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

Ограничение по сетке с одновременной фиксацией границ

Можно комбинировать restrict с модификатором snap, чтобы элемент не только оставался в границах, но и перемещался по дискретной сетке:

interact('.draggable')
  .draggable({
    modifiers: [
      interact.modifiers.snap({
        targets: [interact.createSnapGrid({ x: 50, y: 50 })],
        range: Infinity,
        relativePoints: [{ x: 0, y: 0 }]
      }),
      interact.modifiers.restrict({
        restriction: 'parent',
        endOnly: false
      })
    ]
  });

Такой подход обеспечивает точное позиционирование и одновременное соблюдение границ контейнера.

Особенности и нюансы

  • ЭлементRect влияет на то, какая часть элемента должна оставаться внутри области: верхняя, нижняя или вся.
  • endOnly: true уменьшает нагрузку на браузер, так как ограничение проверяется только при завершении drag.
  • При использовании функции для ограничения возвращаемое значение может быть либо объектом { x, y }, либо DOM-элементом/координатами.
  • Если одновременно задействованы несколько модификаторов, порядок их применения критичен: сначала snap, затем restrict, чтобы позиция сначала скорректировалась по сетке, а потом проверялась на ограничения.

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

  • Ограничение draggable элементов в интерфейсах dashboard и панелей управления.
  • Контейнеры с перетаскиваемыми виджетами, где важно оставаться в пределах родителя.
  • Игровые элементы, где объект должен перемещаться по заданной области.
  • Визуальные редакторы, чтобы блоки или изображения не выходили за рамки холста.

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