<!DOCTYPE html> <html> <head> <script src="https://unpkg.com/[email protected]/konva.min.js"></script> <meta charset="utf-8" /> <title>Konva Drag and Drop Multiple Shapes Demo</title> <style> body { margin: 0; padding: 0; overflow: hidden; background-color: #f0f0f0; } </style> </head> <body> <div id="container"></div> <script> function getCorner(pivotX, pivotY, diffX, diffY, angle) { const distance = Math.sqrt(diffX * diffX + diffY * diffY);
angle += Math.atan2(diffY, diffX);
const x = pivotX + distance * Math.cos(angle); const y = pivotY + distance * Math.sin(angle);
return { x: x, y: y }; } function getClientRect(rotatedBox) { const { x, y, width, height } = rotatedBox; const rad = rotatedBox.rotation;
const p1 = getCorner(x, y, 0, 0, rad); const p2 = getCorner(x, y, width, 0, rad); const p3 = getCorner(x, y, width, height, rad); const p4 = getCorner(x, y, 0, height, rad);
const minX = Math.min(p1.x, p2.x, p3.x, p4.x); const minY = Math.min(p1.y, p2.y, p3.y, p4.y); const maxX = Math.max(p1.x, p2.x, p3.x, p4.x); const maxY = Math.max(p1.y, p2.y, p3.y, p4.y);
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY, }; }
function getTotalBox(boxes) { let minX = Infinity; let minY = Infinity; let maxX = -Infinity; let maxY = -Infinity;
boxes.forEach((box) => { minX = Math.min(minX, box.x); minY = Math.min(minY, box.y); maxX = Math.max(maxX, box.x + box.width); maxY = Math.max(maxY, box.y + box.height); }); return { x: minX, y: minY, width: maxX - minX, height: maxY - minY, }; }
const stage = new Konva.Stage({ container: 'container', width: window.innerWidth, height: window.innerHeight, });
const layer = new Konva.Layer(); stage.add(layer);
const shape1 = new Konva.Rect({ x: stage.width() / 2 - 60, y: stage.height() / 2 - 60, width: 50, height: 50, fill: 'red', draggable: true, }); layer.add(shape1);
const shape2 = shape1.clone({ x: stage.width() / 2 + 10, y: stage.height() / 2 + 10, fill: 'green', }); layer.add(shape2);
const tr = new Konva.Transformer({ nodes: [shape1, shape2], boundBoxFunc: (oldBox, newBox) => { const box = getClientRect(newBox); const isOut = box.x < 0 || box.y < 0 || box.x + box.width > stage.width() || box.y + box.height > stage.height();
if (isOut) { return oldBox; } return newBox; }, }); layer.add(tr);
tr.on('dragmove', () => { const boxes = tr.nodes().map((node) => node.getClientRect()); const box = getTotalBox(boxes); tr.nodes().forEach((shape) => { const absPos = shape.getAbsolutePosition(); const offsetX = box.x - absPos.x; const offsetY = box.y - absPos.y;
const newAbsPos = { ...absPos }; if (box.x < 0) { newAbsPos.x = -offsetX; } if (box.y < 0) { newAbsPos.y = -offsetY; } if (box.x + box.width > stage.width()) { newAbsPos.x = stage.width() - box.width - offsetX; } if (box.y + box.height > stage.height()) { newAbsPos.y = stage.height() - box.height - offsetY; } shape.setAbsolutePosition(newAbsPos); }); }); </script> </body> </html>
|