Web applications that allow users to mark points at specific coordinates and connect those points to form polygons are highly useful. Especially, allowing users to freely draw shapes through interaction can significantly enhance the user experience. Today, we’ll explore how to implement this feature in React using HTML5 `<canvas>` and SVG. Both methods have their own advantages, so you can choose the appropriate one based on your purpose.
Drawing Free Polygons Using HTML5 `<canvas>`
First, let’s look at how to store coordinates and draw polygons by using the click event in the HTML5 `<canvas>` element. `<canvas>` is well-suited for pixel-based graphics operations and is commonly used when real-time user interaction is crucial.
Example Code
import React, { useRef, useState } from 'react';
const CanvasPolygonDrawer = () => {
const canvasRef = useRef(null);
const [points, setPoints] = useState([]);
// Add coordinates on canvas click
const handleCanvasClick = (e) => {
const canvas = canvasRef.current;
const rect = canvas.getBoundingClientRect();
// Convert the mouse click position relative to the canvas
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
setPoints((prevPoints) => [...prevPoints, { x, y }]);
};
// Draw points and lines
const drawPolygon = () => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (points.length > 1) {
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
// Connect the points to draw lines
points.forEach((point, index) => {
if (index > 0) {
ctx.lineTo(point.x, point.y);
}
});
// Connect the first and last points
ctx.closePath();
ctx.stroke();
}
// Mark each point with a dot
points.forEach((point) => {
ctx.beginPath();
ctx.arc(point.x, point.y, 3, 0, 2 * Math.PI);
ctx.fill();
});
};
// Complete the polygon on button click
const handleComplete = () => {
drawPolygon();
};
return (
<div>
<canvas
ref={canvasRef}
width={500}
height={500}
style={{ border: '1px solid black' }}
onClick={handleCanvasClick}
/>
<button onClick={handleComplete}>Complete</button>
</div>
);
};
export default CanvasPolygonDrawer;
Key Functionalities
- Canvas Click: Every time the user clicks on the canvas, the clicked coordinates are saved in an array.
- Drawing Points and Lines: A point is marked at each coordinate, and the points are connected to form lines. The first and last points are connected to complete the shape.
- Completing the Polygon: When the ‘Complete’ button is clicked, the connected points form a finished polygon.
Drawing Free Polygons Using SVG
Now, let’s explore how to implement the same functionality using SVG. SVG is vector-based, so it scales well for zooming in and out, and CSS makes it easy to control styles. It’s ideal for drawing shapes or lines, and it’s useful when higher resolution is desired.
Example Code
import React, { useState } from 'react';
const SvgPolygonDrawer = () => {
const [points, setPoints] = useState([]);
// Add coordinates on SVG click
const handleSvgClick = (e) => {
const svg = e.target;
const rect = svg.getBoundingClientRect();
// Convert the click position relative to the SVG coordinates
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
setPoints((prevPoints) => [...prevPoints, { x, y }]);
};
// Complete the polygon by connecting the first and last points
const handleComplete = () => {
setPoints((prevPoints) => [...prevPoints, prevPoints[0]]);
};
return (
<div>
<svg
width="500"
height="500"
style={{ border: '1px solid black' }}
onClick={handleSvgClick}
>
{/* Draw points */}
{points.map((point, index) => (
<circle key={index} cx={point.x} cy={point.y} r="4" fill="black" />
))}
{/* Draw lines connecting the points */}
{points.length > 1 && (
<polyline
points={points.map((point) => `${point.x},${point.y}`).join(' ')}
fill="none"
stroke="black"
strokeWidth="2"
/>
)}
</svg>
<button onClick={handleComplete}>Complete</button>
</div>
);
};
export default SvgPolygonDrawer;
Key Functionalities
- SVG Click: Every time the user clicks within the SVG area, the coordinates are saved in an array.
- Drawing Points and Lines: Points are marked at each coordinate, and the points are connected to form lines.
- Completing the Polygon: Clicking the ‘Complete’ button finishes the shape by connecting the first and last points automatically.
Conclusion
The ability to mark points at specific coordinates and connect them to draw polygons in React can be implemented using both HTML5 `<canvas>` and SVG. While `<canvas>` is better for pixel-based work and real-time interactions, SVG excels in vector-based operations and style control. Each method has its strengths, so you can choose the one that best fits your project’s characteristics.
References
- MDN Web Docs, “CanvasRenderingContext2D”
- MDN Web Docs, “SVG `<polygon>` and `<polyline>`”