Drag and Drop Multiple Shapes
Instructions: Drag and drop the shapes or remove them by double clicking or double tapping.
- Vanilla
- React
- Vue
import Konva from 'konva';
const width = window.innerWidth;
const height = window.innerHeight;
const stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});
const layer = new Konva.Layer();
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'];
for (let i = 0; i < 6; i++) {
const box = new Konva.Rect({
x: i * 30 + 50,
y: i * 18 + 40,
fill: colors[i],
stroke: 'black',
strokeWidth: 4,
draggable: true,
width: 100,
height: 50,
});
box.on('dragstart', function () {
this.moveToTop();
});
box.on('dragmove', function () {
document.body.style.cursor = 'pointer';
});
// dblclick to remove box for desktop app
// and dbltap to remove box for mobile app
box.on('dblclick dbltap', function () {
this.destroy();
});
box.on('mouseover', function () {
document.body.style.cursor = 'pointer';
});
box.on('mouseout', function () {
document.body.style.cursor = 'default';
});
layer.add(box);
}
// add the layer to the stage
stage.add(layer);
import { useState } from 'react';
import { Stage, Layer, Rect } from 'react-konva';
const App = () => {
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'];
// Initialize boxes with proper IDs and positions
const initialBoxes = colors.map((color, i) => ({
id: i.toString(),
x: i * 30 + 50,
y: i * 18 + 40,
width: 100,
height: 50,
fill: color,
stroke: 'black',
strokeWidth: 4
}));
const [boxes, setBoxes] = useState(initialBoxes);
const handleDragStart = (e) => {
// Move the dragged box to the end of the array to simulate moveToTop
const id = e.target.id();
setBoxes(currentBoxes => {
const box = currentBoxes.find(b => b.id === id);
if (!box) return currentBoxes;
return [...currentBoxes.filter(b => b.id !== id), box];
});
};
const handleDragMove = (e) => {
// Update the position of the box
const id = e.target.id();
setBoxes(currentBoxes => currentBoxes.map(box =>
box.id === id
? { ...box, x: e.target.x(), y: e.target.y() }
: box
));
};
const handleDoubleClick = (id) => {
// Remove the box on double click
setBoxes(currentBoxes => currentBoxes.filter(box => box.id !== id));
};
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
{boxes.map((box) => (
<Rect
key={box.id}
id={box.id}
x={box.x}
y={box.y}
width={box.width}
height={box.height}
fill={box.fill}
stroke={box.stroke}
strokeWidth={box.strokeWidth}
draggable
onDragStart={handleDragStart}
onDragMove={handleDragMove}
onDblClick={() => handleDoubleClick(box.id)}
onDblTap={() => handleDoubleClick(box.id)}
onMouseOver={(e) => {
document.body.style.cursor = 'pointer';
}}
onMouseOut={(e) => {
document.body.style.cursor = 'default';
}}
/>
))}
</Layer>
</Stage>
);
};
export default App;
<template>
<v-stage :config="stageConfig">
<v-layer>
<v-rect
v-for="box in boxes"
:key="box.id"
:config="box"
@dragstart="handleDragStart"
@dragmove="handleDragMove"
@mouseover="handleMouseOver"
@mouseout="handleMouseOut"
@dblclick="handleDoubleClick"
@dbltap="handleDoubleClick"
/>
</v-layer>
</v-stage>
</template>
<script setup>
import { ref } from 'vue';
const stageConfig = {
width: window.innerWidth,
height: window.innerHeight
};
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'];
// Initialize boxes with proper configuration
const initialBoxes = colors.map((color, i) => ({
id: i.toString(),
x: i * 30 + 50,
y: i * 18 + 40,
width: 100,
height: 50,
fill: color,
stroke: 'black',
strokeWidth: 4,
draggable: true
}));
const boxes = ref(initialBoxes);
const handleDragStart = (e) => {
const id = e.target.id();
// Move the dragged box to the end of the array to simulate moveToTop
const box = boxes.value.find(b => b.id === id);
const filteredBoxes = boxes.value.filter(b => b.id !== id);
boxes.value = [...filteredBoxes, box];
};
const handleDragMove = (e) => {
const id = e.target.id();
const index = boxes.value.findIndex(b => b.id === id);
if (index !== -1) {
// Update position
const updatedBox = { ...boxes.value[index] };
updatedBox.x = e.target.x();
updatedBox.y = e.target.y();
// Replace the box in the array
const newBoxes = [...boxes.value];
newBoxes[index] = updatedBox;
boxes.value = newBoxes;
}
document.body.style.cursor = 'pointer';
};
const handleMouseOver = () => {
document.body.style.cursor = 'pointer';
};
const handleMouseOut = () => {
document.body.style.cursor = 'default';
};
const handleDoubleClick = (e) => {
const id = e.target.id();
// Remove the box
boxes.value = boxes.value.filter(box => box.id !== id);
};
</script>