Привязка к другим элементам

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

Настройка базового взаимодействия

Для начала необходимо подключить Interact.js и определить элемент, который будет перетаскиваться:

interact('.draggable')
  .draggable({
    inertia: true,
    modifiers: [
      interact.modifiers.restrictRect({
        restriction: 'parent',
        endOnly: true
      })
    ],
    listeners: {
      move: dragMoveListener
    }
  });

function dragMoveListener(event) {
  const target = event.target;
  const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
  const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;

  target.style.transform = `translate(${x}px, ${y}px)`;
  target.setAttribute('data-x', x);
  target.setAttribute('data-y', y);
}

Ключевой момент: event.dx и event.dy содержат смещение за один шаг движения, что позволяет плавно обновлять позицию элемента.

Использование snap для привязки

Механизм snap в Interact.js позволяет элементу автоматически «прилипать» к определённым координатам, сетке или другому элементу. Пример привязки к координатной сетке:

interact('.draggable').draggable({
  modifiers: [
    interact.modifiers.snap({
      targets: [
        interact.createSnapGrid({ x: 50, y: 50 })
      ],
      range: Infinity,
      relativePoints: [{ x: 0.5, y: 0.5 }]
    })
  ],
  listeners: { move: dragMoveListener }
});

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

  • targets – массив объектов, к которым будет происходить привязка.
  • range – расстояние, на котором элемент начинает «прилипать».
  • relativePoints – точка внутри элемента, которая учитывается при привязке.

Привязка к другому элементу

Для создания зависимого движения используется метод interact.createSnapGrid или более гибкая конструкция с функцией targets. Например, привязка к другому элементу .target:

const targetElement = document.querySelector('.target');

interact('.draggable').draggable({
  modifiers: [
    interact.modifiers.snap({
      targets: [
        function (x, y) {
          const rect = targetElement.getBoundingClientRect();
          return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
        }
      ],
      range: 30,
      relativePoints: [{ x: 0.5, y: 0.5 }]
    })
  ],
  listeners: { move: dragMoveListener }
});

Элемент .draggable будет «прилипать» к центру .target при приближении на 30 пикселей.

Динамическая привязка к нескольким элементам

Если требуется, чтобы элемент мог привязываться к нескольким целям одновременно, можно использовать массив функций:

const targets = Array.from(document.querySelectorAll('.snap-target'));

interact('.draggable').draggable({
  modifiers: [
    interact.modifiers.snap({
      targets: targets.map(t => (x, y) => {
        const rect = t.getBoundingClientRect();
        return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
      }),
      range: 40,
      relativePoints: [{ x: 0.5, y: 0.5 }]
    })
  ],
  listeners: { move: dragMoveListener }
});

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

Настройка плавного следования

Иногда требуется, чтобы элемент не просто «прыгал» к цели, а следовал плавно. Для этого можно использовать интерполяцию внутри обработчика движения:

function dragMoveListener(event) {
  const target = event.target;
  let x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
  let y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;

  if (target.snap) {
    x += (target.snap.x - x) * 0.2;
    y += (target.snap.y - y) * 0.2;
  }

  target.style.transform = `translate(${x}px, ${y}px)`;
  target.setAttribute('data-x', x);
  target.setAttribute('data-y', y);
}

Здесь 0.2 – коэффициент сглаживания, который регулирует скорость следования к цели.

События привязки

Interact.js поддерживает события, связанные с snap:

  • snapstart – начало привязки
  • snapmove – движение во время привязки
  • snapend – завершение привязки

Пример регистрации:

interact('.draggable').on('snapmove', function (event) {
  console.log('Элемент привязан к координатам:', event.snap.x, event.snap.y);
});

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

Комбинирование с другими модификаторами

Snap можно сочетать с другими модификаторами Interact.js:

  • restrictRect – ограничение движения рамкой.
  • restrictEdges – запрет выхода за границы.
  • restrictSize – ограничение размера элемента.

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

interact('.draggable').draggable({
  modifiers: [
    interact.modifiers.restrictRect({ restriction: 'parent' }),
    interact.modifiers.snap({
      targets: [interact.createSnapGrid({ x: 50, y: 50 })],
      range: 20
    })
  ],
  listeners: { move: dragMoveListener }
});

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

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

  • Визуальные редакторы: привязка объектов друг к другу для точного выравнивания.
  • Drag-and-drop интерфейсы: автоматическая «прилипка» элементов к зонам назначения.
  • Игровые интерфейсы: механика соединения объектов, пазлов, элементов карты.
  • Интерактивные диаграммы и панели: выравнивание и группировка блоков при перетаскивании.

Использование привязки через Interact.js сочетает гибкость и контроль: можно создавать как простую сетку, так и динамически рассчитываемые цели с индивидуальными поведениями.