Для работы с drag-and-drop необходимо сначала создать экземпляр
Two.js и привязать его к DOM-элементу. Обычно
используется элемент <div> как контейнер:
const elem = document.getElementById('draw-area');
const two = new Two({
width: 800,
height: 600,
type: Two.Types.canvas
}).appendTo(elem);
Здесь width и height задают размеры сцены,
а type определяет рендерер: canvas,
svg или webgl. После этого создаётся базовая
сцена, на которую можно добавлять фигуры.
Two.js предоставляет несколько встроенных фигур: Rectangle, Circle, Ellipse, Polygon, Path. Для drag-and-drop важны следующие свойства:
position.x и position.y — координаты
центра фигуры.translation — альтернатива position,
используемая для смещения.draggable — логика перемещения задаётся вручную через
обработчики событий мыши.Пример создания круга:
const circle = two.makeCircle(100, 100, 50);
circle.fill = '#FF8000';
circle.stroke = '#000000';
circle.linewidth = 2;
Добавление фигур в сцену автоматически отображает их после вызова:
two.update();
Two.js сам по себе не реализует drag-and-drop. Для этого используются
нативные события браузера: mousedown,
mousemove, mouseup.
let selected = null;
elem.addEventListener('mousedown', function(event) {
const rect = elem.getBoundingClientRect();
const mouseX = event.clientX - rect.left;
const mouseY = event.clientY - rect.top;
two.scene.children.forEach(shape => {
if (shape.contains(mouseX, mouseY)) {
selected = shape;
selected.offset = {
x: mouseX - shape.translation.x,
y: mouseY - shape.translation.y
};
}
});
});
elem.addEventListener('mousemove', function(event) {
if (selected) {
const rect = elem.getBoundingClientRect();
selected.translation.x = event.clientX - rect.left - selected.offset.x;
selected.translation.y = event.clientY - rect.top - selected.offset.y;
two.update();
}
});
elem.addEventListener('mouseup', function() {
selected = null;
});
Ключевые моменты:
shape.contains(x, y) — метод, проверяющий попадание
курсора внутрь фигуры. Для кастомных фигур может потребоваться вручную
реализовать проверку.translation изменяет положение фигуры без пересоздания
объекта.Для сложных сцен с группами объектов полезно работать с локальными координатами. Two.js позволяет объединять объекты в Group:
const group = two.makeGroup(circle, rectangle);
group.translation.set(200, 200);
Drag-and-drop может применяться как к отдельным фигурам, так и к группам:
if (selectedGroup) {
selectedGroup.translation.x = mouseX - selectedGroup.offset.x;
selectedGroup.translation.y = mouseY - selectedGroup.offset.y;
}
При этом смещение внутри группы сохраняет относительное расположение дочерних объектов.
Для реализации ограничений перемещения можно проверять новые координаты перед их присвоением:
const minX = 0, maxX = 800;
const minY = 0, maxY = 600;
selected.translation.x = Math.min(Math.max(mouseX - selected.offset.x, minX), maxX);
selected.translation.y = Math.min(Math.max(mouseY - selected.offset.y, minY), maxY);
Для столкновений между объектами можно использовать bounding box:
function isColliding(a, b) {
const ax = a.translation.x, ay = a.translation.y;
const bx = b.translation.x, by = b.translation.y;
return Math.abs(ax - bx) < (a.width/2 + b.width/2) &&
Math.abs(ay - by) < (a.height/2 + b.height/2);
}
Для плавного движения можно использовать метод
Two.js two.bind('update', callback):
two.bind('update', function() {
if (selected) {
// Здесь можно реализовать плавное смещение с инерцией
selected.translation.x += (targetX - selected.translation.x) * 0.1;
selected.translation.y += (targetY - selected.translation.y) * 0.1;
}
}).play();
Это позволяет создавать эффект “тянущегося” объекта, когда фигура плавно движется к курсору.
Для touch-событий используются touchstart,
touchmove, touchend с аналогичной логикой:
elem.addEventListener('touchstart', function(event) {
const touch = event.touches[0];
// логика как для mousedown
});
elem.addEventListener('touchmove', function(event) {
const touch = event.touches[0];
// логика как для mousemove
event.preventDefault();
}, { passive: false });
elem.addEventListener('touchend', function() {
selected = null;
});
Важно использовать event.preventDefault() для
предотвращения скролла на мобильных устройствах при drag-and-drop.
contains.Эти методы позволяют создавать полноценные интерактивные сцены с динамическими объектами, полностью управляемыми через drag-and-drop с Two.js.