My code contains a toolbar, it’s about a dropdown. When pass is selected it should enable the ability to create an arrow by drag and dropping on the canvas. I use JS React with useState and useEffect. Here’s the important snippets:
const handleFieldMouseDown = (event) => {
const rect = canvasRef.current.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
if (addingArrow) {
setArrowStartPoint({ x, y });
} else if (addingArea) {
setAreaStart({ x, y });
// Handle other elements as usual
};
}
const handleFieldMouseMove = useCallback((event) => {
const rect = canvasRef.current.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
if (addingArrow && arrowStartPoint) {
drawArrow(arrowStartPoint, { x, y });
} else if (addingArea && areaStart) {
setPreviewArea({
x: Math.min(areaStart.x, x),
y: Math.min(areaStart.y, y),
width: Math.abs(x - areaStart.x),
height: Math.abs(y - areaStart.y)
});
}
// Call drawArrow to update the arrow drawing
}, [arrowStartPoint, addingArrow, addingArea, areaStart]);
const handleFieldMouseUp = (event) => {
const rect = canvasRef.current.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
if (addingArrow) {
setArrowEndPoint({ x, y });
const newArrow = {
start: arrowStartPoint,
end: arrowEndPoint,
type: arrowType,
};
drawArrow(arrowStartPoint, arrowEndPoint);
setArrows((arrows) => [...arrows, newArrow]);
setArrowStartPoint(null);
setArrowEndPoint(null);
setIsDrawingArrow(false);
}else if (addingArea && areaStart) {
const createdArea = {
x: Math.min(areaStart.x, x),
y: Math.min(areaStart.y, y),
width: Math.abs(x - areaStart.x),
height: Math.abs(y - areaStart.y),
};
setAreas((areas) => [...areas, createdArea]);
setAreaStart(null);
setPreviewArea(null);
setAddingGoal(false);
setAddingCone(false);
setAddingNumber(false);
setAddingBall(false);
setAddingPlayer(false);
setAddingArrow(false);
}
};
const Arrow = ({ start, end }) => {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
const drawArrow = (start, end, ctx) => {
// Check if arrowStartPoint is not null
// decide which type of arrow to draw
switch (arrowType) {
case 'pass':
ctx.beginPath();
ctx.moveTo(start.x, start.y);
ctx.lineTo(end.x, end.y);
ctx.strokeStyle = 'black'; // Arrow color
ctx.lineWidth = 2;
ctx.stroke();
break;
case 'run':
// draw a dashed arrow
break;
case 'dribbling':
// draw a wavy arrow
break;
case 'highball':
// draw a slightly curved arrow
break;
default:
break;
}
};
drawArrow();
}, [start, end]);
return <canvas ref={canvasRef} />;
};
useEffect(drawArrow, [arrowType]);
useEffect(() => {
if (goalImage === null) {
// If goalImage is not yet loaded, don't attempt to draw it
return;
}
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
// Clear the field
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Redraw the field
drawField();
// Draw each player
for (const player of players) {
ctx.beginPath();
ctx.arc(player.x, player.y, 10 /* player size */, 0, Math.PI * 2);
ctx.fillStyle = 'blue'; // player color
ctx.fill();
// Draw player number
ctx.fillStyle = 'white'; // text color
ctx.fillText(player.id, player.x-3, player.y+3); // adjust these values as needed
}
// Create a new image object and set its source
const ballImg = new Image();
ballImg.src = ballImage;
// Draw each ball when the image has loaded
ballImg.onload = () => {
for (const ball of balls) {
// Draw the image at the ball's position
ctx.drawImage(ballImg, ball.x, ball.y, 16, 16); // Adjust the size (14, 14 here) as needed
}
};
// Draw arrows
for (const arrow of arrows) {
Arrow(arrow.start, arrow.end, ctx);
}
// Draw each area
for (const area of areas) {
ctx.beginPath();
ctx.rect(area.x, area.y, area.width, area.height);
ctx.fillStyle = 'rgba(0, 0, 255, 0.5)';
ctx.fill();
}
}, [players, balls, mousePosition, areas, arrows]);
I want that the arrow appears when dragging and dropping. The Arrow shows on Mouse down but as soon as I lift my Mouse the arrow disappears.