Drawing shapes with canvas
Remember the SVG module where we learned how to draw various shapes on the screen? Now, we'll be doing this again, but with canvas
instead—and the approach is quite different!
Let's make some circles again! 🎉
Let's make a circle (again)
📍 Start with a canvas
element
Everything begins with the DOM. In the return
statement of our graph component, rather than rendering multiple SVG elements as we did previously,
we now render just a single canvas
element.
return (
<canvas width={width} height={height} ref={canvasRef}/>
);
⛏️useRef
and useEffect
to draw in it
This approach is called imperative programming, as opposed to declarative programming, where we define everything directly in the DOM, like we did with SVG.
Next, we’ll need to “edit” the canvas by drawing on it. To achieve this, we need a reference to the canvas element so we can target it directly. Then, we can use useEffect
to write the code for drawing inside it.
// define a ref = a way to target the canvas element
const canvasRef = useRef(null);
// once the canvas element is mounted, draw some stuff in it imperatively
useEffect(() => {
const canvas = canvasRef.current; // find the target canvas element
const ctx = canvas.getContext('2d'); // initialize a canvas "context"
// draw whatever you want in the canvas
}, []);
✏️ A new syntax for the actual drawing
Finally, it’s time to create the actual drawing.
For each element, we start by initializing a path with beginPath()
. There are various functions available for drawing different shapes. To draw a circle, for example, we use the arc()
function.
Setting a color follows a slightly unusual pattern: first, we set the color with fillStyle()
, and then we apply the fill using fill()
.
ctx.beginPath();
ctx.arc(100, 100, 50, 0, 2 * Math.PI);
ctx.fillStyle = 'blue';
ctx.fill();
🔵 Complete circle example
A simple circle drawn with canvas
🟪 What about rectangles?
The process is almost identical!
The only change is the canvas call inside useEffect
. This time, we’ll use the rect()
function as shown:
ctx.beginPath();
ctx.rect(100, 100, 80, 50); // Draw the rectangle (x, y, width, height)
ctx.fillStyle = "purple";
ctx.fill();
And that’s it! Here’s a complete example:
A simple Rectangle drawn with canvas
🍔 Stacking Order Matters
Drawing with canvas is a bit like using a pen on paper: whatever you draw second will always appear on top of what was drawn first!
For data visualizations, we need to carefully consider the stacking order, as there’s no way to change it afterward.
Similarly, individual elements can’t be removed from the canvas. The only option is to redraw everything from scratch—which isn’t an issue since it’s very fast.
A few shapes drawn with canvas