Interact.js — это мощная библиотека для реализации интерактивных элементов на веб-странице. Она позволяет создавать перетаскиваемые, изменяемые по размеру и отзывчивые элементы без сложных обработчиков событий.
Для перетаскивания карточек на канбан-доске используется метод
interact().draggable(). Простейший пример выглядит так:
interact('.kanban-card')
.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);
}
Ключевые моменты:
inertia: true добавляет плавность перемещения.restrictRect ограничивает движение элементами внутри
контейнера.data-x и data-y
необходимо для правильного расчёта относительного смещения при каждом
событии.Для перемещения карточек между колонками канбан-доски используются drop-зоны. Основной синтаксис:
interact('.kanban-column').dropzone({
accept: '.kanban-card',
overlap: 0.75, // сколько элемента должно пересекать зону для активации drop
ondropactivate: function(event) {
event.target.classList.add('drop-active');
},
ondragenter: function(event) {
const draggableElement = event.relatedTarget;
event.target.classList.add('drop-target');
draggableElement.classList.add('can-drop');
},
ondragleave: function(event) {
event.target.classList.remove('drop-target');
event.relatedTarget.classList.remove('can-drop');
},
ondrop: function(event) {
event.target.appendChild(event.relatedTarget);
event.relatedTarget.style.transform = 'translate(0,0)';
event.relatedTarget.setAttribute('data-x', 0);
event.relatedTarget.setAttribute('data-y', 0);
},
ondropdeactivate: function(event) {
event.target.classList.remove('drop-active');
event.target.classList.remove('drop-target');
}
});
Ключевые моменты:
accept задаёт, какие элементы разрешены для drop.overlap позволяет настраивать чувствительность
попадания элемента в drop-зону.ondrop важно сбрасывать трансформацию, чтобы карточка
корректно вставала в колонку.Иногда нужно менять размеры карточек, например, при добавлении
дополнительных деталей. Interact.js поддерживает
resizable:
interact('.kanban-card')
.resizable({
edges: { left: true, right: true, bottom: true, top: false },
listeners: {
move(event) {
let { x, y } = event.target.dataset;
x = parseFloat(x) || 0;
y = parseFloat(y) || 0;
Object.assign(event.target.style, {
width: `${event.rect.width}px`,
height: `${event.rect.height}px`,
transform: `translate(${x}px, ${y}px)`
});
}
},
modifiers: [
interact.modifiers.restrictSize({
min: { width: 100, height: 50 },
max: { width: 500, height: 300 }
})
],
inertia: true
});
Ключевые моменты:
edges определяет, с каких сторон можно изменять
размеры.restrictSize ограничивает минимальные и максимальные
размеры элемента.draggable.Interact.js предоставляет богатый набор событий, которые позволяют реагировать на пользовательские действия:
dragstart — начало перетаскивания.dragmove — движение элемента.dragend — завершение перемещения.dropactivate / dropdeactivate — активация
и деактивация drop-зоны.resizemove — изменение размера элемента.Использование этих событий позволяет создавать динамичные реакции интерфейса, например, подсвечивание колонок, отображение индикаторов места для вставки карточки, анимацию перестановки элементов.
Для аккуратного расположения карточек в колонках полезно использовать сетку и привязку к ней:
interact('.kanban-card').draggable({
modifiers: [
interact.modifiers.snap({
targets: [interact.snappers.grid({ x: 10, y: 10 })],
range: Infinity,
relativePoints: [{ x: 0, y: 0 }]
})
]
});
Ключевые моменты:
snap обеспечивает привязку к виртуальной сетке, что
улучшает визуальное выравнивание.range: Infinity позволяет привязываться на любом
расстоянии, можно ограничить, чтобы snap срабатывал только вблизи
grid.Для больших досок с множеством карточек важно:
requestAnimationFrame внутри
dragMoveListener для плавной анимации.dragmove и resizemove.transform, а не
top/left, чтобы задействовать GPU-ускорение.Перемещение и изменение размеров карточек должны синхронизироваться с данными. Например, при drop:
const cardId = event.relatedTarget.dataset.id;
const columnId = event.target.dataset.id;
updateBoardState(cardId, columnId);
Ключевой момент: хранить координаты и размеры карточек в объекте состояния доски, чтобы при перезагрузке интерфейс мог восстановить позицию элементов.
Interact.js позволяет создавать канбан-доски с функционалом перетаскивания, изменения размеров, snap-сеток, ограничений и инерции. В сочетании с правильной структурой данных это даёт полностью интерактивный, отзывчивый и удобный интерфейс для работы с задачами.