Chapter 51: Canvas Clipping
Canvas Clipping in the clearest, most patient, step-by-step way possible.
Imagine I’m sitting right next to you with my laptop open. We’re going to build every concept together — slowly, with tiny complete runnable examples you can copy-paste immediately. No skipping steps, no magic, just plain English explanations, visual thinking, common beginner traps, and repeated patterns until clipping feels completely natural and easy to control.
Canvas Clipping – From Zero to Confident
1. The single most important sentence about clipping in Canvas
Clipping in Canvas is a way to say: “From now on, only draw inside this shape — ignore / hide everything outside it.”
It is not deleting pixels permanently. It is temporarily restricting where the painter is allowed to put ink — everything drawn outside the clip region is simply not painted (invisible), even if you try to draw it.
Clipping is temporary and cumulative — you can add more clipping regions, but you usually want to restore the full canvas afterward.
2. The two main ways to clip in Canvas (you will use these 95% of the time)
| Method | Command / Pattern | When to use it | Difficulty | Reset needed? |
|---|---|---|---|---|
| Clip with any path | ctx.beginPath(); … describe shape … ctx.clip() | Any shape: circle, star, polygon, text, custom path | ★★☆☆☆ | Yes (save/restore) |
| Clip with rectangle | ctx.rect(x,y,w,h); ctx.clip() or ctx.clipRect() (rare) | Quick rectangular masks | ★☆☆☆☆ | Yes |
Golden rule (memorize this):
ctx.clip() locks in the current path as the visible region. All future drawing (until you restore) can only happen inside that path.
3. Minimal complete clipping example (copy → run)
|
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 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Canvas – First Clipping</title> <style> canvas { border: 1px solid #ccc; background: #f8f9fa; display: block; margin: 40px auto; } </style> </head> <body> <canvas id="c" width="600" height="400"></canvas> <script> const canvas = document.getElementById('c'); const ctx = canvas.getContext('2d'); // Step 1: Draw a big red rectangle that would cover the whole canvas ctx.fillStyle = '#F44336'; ctx.fillRect(0, 0, canvas.width, canvas.height); // Step 2: Save the current state (very important!) ctx.save(); // Step 3: Define a clipping region (a circle in the center) ctx.beginPath(); ctx.arc(300, 200, 120, 0, Math.PI * 2); // circle at center ctx.clip(); // ← now only inside circle is visible! // Step 4: Draw something big — but only the part inside the circle shows ctx.fillStyle = '#4CAF50'; ctx.fillRect(0, 0, canvas.width, canvas.height); // this would fill everything, but only circle area shows // Step 5: Restore original state (remove clipping) ctx.restore(); // Label ctx.font = 'bold 28px Arial'; ctx.fillStyle = '#333'; ctx.textAlign = 'center'; ctx.fillText('Only the green circle area was visible during fill', 300, 360); </script> </body> </html> |
What you should see & remember forever:
- Red rectangle fills the whole canvas first (no clipping yet)
- After ctx.clip() → only inside the circle is allowed
- Green fill tries to cover everything → but only circle area actually appears
- ctx.restore() → turns clipping off → future drawing is normal again
Key rule: clip() does not erase anything already drawn — it only restricts future drawing.
4. Example 2 – Clipping text, images, and multiple shapes
|
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 |
<canvas id="c2" width="800" height="500"></canvas> <script> const canvas = document.getElementById('c2'); const ctx = canvas.getContext('2d'); // Save state before clipping ctx.save(); // Clip to a star shape ctx.beginPath(); const cx = 400, cy = 250, r = 180; for (let i = 0; i < 10; i++) { const angle = (i * Math.PI / 5) - Math.PI / 2; const radius = (i % 2 === 0) ? r : r / 2; ctx.lineTo(cx + Math.cos(angle) * radius, cy + Math.sin(angle) * radius); } ctx.closePath(); ctx.clip(); // Now draw a big image / gradient / anything — only star shape will show ctx.fillStyle = '#2196F3'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.font = 'bold 120px Arial'; ctx.fillStyle = 'white'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText('STAR', cx, cy); // Restore — clipping is gone ctx.restore(); // Draw the star outline so we can see the clipping region ctx.beginPath(); for (let i = 0; i < 10; i++) { const angle = (i * Math.PI / 5) - Math.PI / 2; const radius = (i % 2 === 0) ? r : r / 2; ctx.lineTo(cx + Math.cos(angle) * radius, cy + Math.sin(angle) * radius); } ctx.closePath(); ctx.strokeStyle = '#333'; ctx.lineWidth = 4; ctx.stroke(); ctx.fillStyle = '#333'; ctx.font = 'bold 28px Arial'; ctx.textAlign = 'center'; ctx.fillText('Everything was clipped to the star shape', 400, 460); </script> |
Key lessons from this example:
- You can clip to any path — not just rectangles or circles
- Text, gradients, images — all respect the clip region
- save() / restore() is the clean way to apply clipping temporarily
5. Common real-world patterns you’ll reuse
Pattern 1 – Circular avatar / profile picture
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
ctx.save(); ctx.beginPath(); ctx.arc(100, 100, 80, 0, Math.PI*2); ctx.clip(); // Now draw image — only circle part will be visible ctx.drawImage(img, 20, 20, 160, 160); ctx.restore(); |
Pattern 2 – Fade edges / vignette (combine with globalAlpha)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
ctx.save(); ctx.globalAlpha = 0.7; // semi-transparent black overlay ctx.fillStyle = 'black'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.globalAlpha = 1; ctx.beginPath(); ctx.arc(cx, cy, 200, 0, Math.PI*2); ctx.clip(); // now only inside circle is visible // Draw your main content here — edges will be faded ctx.restore(); |
6. Your three tiny practice tasks (10–15 min each)
Task 1 – Circular photo Load any online image Clip it to a perfect circle in the center of the canvas Add a thick white stroke around the circle
Task 2 – Star-shaped text Clip to a 5-point star (copy the star path from earlier example) Fill the whole canvas with blue Draw large white centered text “STAR POWER” — only star area shows
Task 3 – Multiple clips Draw a red rectangle Clip to a circle inside it Draw green fill inside the clip → only circular part of rectangle is green
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?
- Why clip() only affects future drawing, not past?
- Difference between clipping to circle vs clipping to star/text?
- Why we must use save() / restore() with clipping?
- How clipping works with images vs shapes?
- Combining clipping with gradients or shadows?
- Something else?
Tell me — we’ll stay on clipping until you feel super confident using it to create any masked or cut-out effect you imagine.
You’re doing really well — clipping is one of the most powerful tools in Canvas for creative compositions! 🚀
