How to listen to an event on a canvas shape with React and Konva?
With react-konva you can attach any events that Konva supports to canvas nodes.
To do that you can use the onEventName scheme, like onMouseDown for mousedown, onDragEnd for dragend, etc.
For the full list of events take a look into the on() method documentation.
In this demo you can see how we are using dragstart and dragend events to create an interactive star field:
import React from 'react';
import { Stage, Layer, Star, Text } from 'react-konva';
function generateShapes() {
return [...Array(10)].map((_, i) => ({
id: i.toString(),
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight,
rotation: Math.random() * 180,
isDragging: false,
}));
}
const App = () => {
const [stars, setStars] = React.useState(generateShapes());
const handleDragStart = (e) => {
const id = e.target.id();
setStars((currentStars) =>
currentStars.map((star) => {
return {
...star,
isDragging: star.id === id,
};
})
);
};
const handleDragEnd = (e) => {
const id = e.target.id();
const position = e.target.position();
setStars((currentStars) =>
currentStars.map((star) => {
return {
...star,
isDragging: false,
...(star.id === id ? position : {}),
};
})
);
};
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<Text text="Try to drag a star" />
{stars.map((star) => (
<Star
key={star.id}
id={star.id}
x={star.x}
y={star.y}
numPoints={5}
innerRadius={20}
outerRadius={40}
fill="#89b717"
opacity={0.8}
draggable
rotation={star.rotation}
shadowColor="black"
shadowBlur={10}
shadowOpacity={0.6}
shadowOffsetX={star.isDragging ? 10 : 5}
shadowOffsetY={star.isDragging ? 10 : 5}
scaleX={star.isDragging ? 1.2 : 1}
scaleY={star.isDragging ? 1.2 : 1}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
/>
))}
</Layer>
</Stage>
);
};
export default App;