Chapter 38: Canvas Shapes
Canvas Shapes in the clearest, most patient, step-by-step way possible.
Imagine I’m sitting right next to you. We’re going to build every single example together — slowly, with tiny complete code snippets you can copy-paste and run immediately. No skipping steps, no magic, just plain English explanations, visual thinking, common mistakes highlighted, and repeated patterns until everything feels natural and confident.
Canvas Shapes – Complete Beginner-to-Confident Guide
1. The single most important mental model about shapes in Canvas
In Canvas, a “shape” is not a permanent object like in SVG (where you can later say “move this rectangle” or “change its color”).
A shape in Canvas is just a path you describe once, then you tell the painter:
- “fill it” → paint the inside pixels
- “stroke it” → paint the outline pixels
- or both
After fill() or stroke() the pixels are done — there is no shape object you can edit later. If you want to move it, change color, or resize it → you have to erase the old pixels and draw a new shape at the new position/color/size.
That’s why almost every Canvas program redraws everything every frame (animation loop).
2. The universal 4-step recipe for any shape in Canvas
You will type this pattern thousands of times — memorize it:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
ctx.beginPath(); // 1. Start a fresh path (forget previous unfinished paths) ctx.moveTo(x1, y1); // 2. Jump to starting point (pen up, no line yet) ctx.lineTo(x2, y2); // 3. Draw line to next point (repeat as needed) ctx.arc(...); // or add curves, arcs, etc. ctx.closePath(); // 4. Optional – connect back to start ctx.fillStyle = '...'; // choose fill color ctx.fill(); // paint inside ctx.strokeStyle = '...'; // choose outline color ctx.lineWidth = 6; ctx.stroke(); // paint outline |
Important rule: beginPath() is almost always needed before a new shape — otherwise the new shape connects to the previous unfinished path.
3. All basic Canvas shapes – one complete example
Copy-paste and run this — it shows every common shape in one canvas with labels.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Canvas – All Basic Shapes</title> <style> canvas { border: 1px solid #ccc; background: #f8f9fa; display: block; margin: 40px auto; } </style> </head> <body> <canvas id="c" width="900" height="500"></canvas> <script> const canvas = document.getElementById('c'); const ctx = canvas.getContext('2d'); ctx.font = 'bold 18px Arial'; ctx.textAlign = 'center'; ctx.fillStyle = '#333'; // ─── Rectangle (filled + stroked) ctx.beginPath(); ctx.rect(80, 80, 180, 120); // x, y, width, height ctx.fillStyle = '#4CAF50'; ctx.fill(); ctx.strokeStyle = '#2E7D32'; ctx.lineWidth = 6; ctx.stroke(); ctx.fillText('Rectangle', 170, 230); // ─── Rounded rectangle (using arc + lines) ctx.beginPath(); const rx = 20, ry = 20; ctx.moveTo(340 + rx, 80); ctx.lineTo(340 + 180 - rx, 80); ctx.arc(340 + 180 - rx, 80 + ry, ry, -Math.PI/2, 0); ctx.lineTo(340 + 180, 80 + 120 - ry); ctx.arc(340 + 180 - rx, 80 + 120 - ry, ry, 0, Math.PI/2); ctx.lineTo(340 + rx, 80 + 120); ctx.arc(340 + rx, 80 + 120 - ry, ry, Math.PI/2, Math.PI); ctx.lineTo(340, 80 + ry); ctx.arc(340 + rx, 80 + ry, ry, Math.PI, Math.PI*1.5); ctx.closePath(); ctx.fillStyle = '#2196F3'; ctx.fill(); ctx.strokeStyle = '#0D47A1'; ctx.lineWidth = 6; ctx.stroke(); ctx.fillText('Rounded Rect', 430, 230); // ─── Circle ctx.beginPath(); ctx.arc(680, 140, 80, 0, Math.PI*2); ctx.fillStyle = '#FF9800'; ctx.fill(); ctx.strokeStyle = '#EF6C00'; ctx.lineWidth = 10; ctx.stroke(); ctx.fillText('Circle', 680, 250); // ─── Ellipse (stretched circle) ctx.beginPath(); ctx.ellipse(170, 380, 120, 60, 0, 0, Math.PI*2); ctx.fillStyle = '#673AB7'; ctx.fill(); ctx.strokeStyle = '#512DA8'; ctx.lineWidth = 8; ctx.stroke(); ctx.fillText('Ellipse', 170, 480); // ─── Line ctx.beginPath(); ctx.moveTo(340, 300); ctx.lineTo(680, 300); ctx.lineTo(680, 420); ctx.lineTo(340, 420); ctx.closePath(); ctx.strokeStyle = '#E91E63'; ctx.lineWidth = 12; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.stroke(); ctx.fillText('Polyline / Polygon path', 510, 480); </script> </body> </html> |
What you should see & remember forever:
- Rectangle → easiest (built-in rect() / fillRect / strokeRect)
- Rounded rectangle → manual path with arc() + lineTo()
- Circle → arc(cx, cy, r, 0, Math.PI*2)
- Ellipse → ellipse(cx, cy, rx, ry, rotation, start, end)
- Line / polyline → moveTo + multiple lineTo
4. Quick reference – All common shape commands
| Shape / Goal | Code pattern (after beginPath()) |
|---|---|
| Rectangle | ctx.rect(x, y, w, h) or ctx.fillRect(x,y,w,h) |
| Rounded rectangle | ctx.roundRect(x, y, w, h, radius) (modern browsers 2024+) |
| Circle | ctx.arc(cx, cy, r, 0, Math.PI*2) |
| Ellipse | ctx.ellipse(cx, cy, rx, ry, 0, 0, Math.PI*2) |
| Simple line | ctx.moveTo(x1,y1); ctx.lineTo(x2,y2); |
| Polyline / polygon | ctx.moveTo(…); ctx.lineTo(…); … ctx.closePath(); |
| Quadratic curve | ctx.quadraticCurveTo(controlX, controlY, endX, endY) |
| Cubic Bézier curve | ctx.bezierCurveTo(c1x,c1y, c2x,c2y, endX,endY) |
5. Your three tiny practice tasks (10–15 minutes each)
Task 1 – Flag Draw a simple flag:
- big rectangle background
- circle in the center
- one diagonal line crossing through the circle
Task 2 – House Rectangle base + triangle roof + rectangle door + small circle window
Task 3 – Traffic light Three stacked circles (red on top, yellow middle, green bottom)
- black outlines on all three
Paste any of them here when you finish — I’ll review it like we’re pair-programming together.
Which part still feels a little slippery?
- Difference between fillRect vs rect + fill()?
- Why we need beginPath() before every new shape?
- How to make rounded rectangles?
- Ellipse vs circle?
- Something else?
Tell me — we’ll stay on shapes until you feel super confident drawing anything you imagine.
You’re doing really well — shapes are the foundation of 95% of Canvas art! 🚀
