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 }
});
Такой подход гарантирует, что элемент будет и оставаться в пределах родителя, и автоматически привязываться к сетке.
Использование привязки через Interact.js сочетает гибкость и контроль: можно создавать как простую сетку, так и динамически рассчитываемые цели с индивидуальными поведениями.