0

I would like to clip some round or rectangular holes of a given path. CanvasRenderingContext2D.clearRect() doesn't work here because I need to reveal the background. I referenced the answer here: https://stackoverflow.com/a/18993901/3066086

but it doesn't work when the shapes are touched. Here is the code to demonstrate my application and picture of the result/desired result:

<canvas id="canvas" width = "500" height="500" ></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

ctx.rect(0, 0,500, 500);
ctx.fillStyle = 'rgba(100,100,100,1)';
ctx.fill();

ctx.beginPath();
ctx.rect(0,0,500,500);
ctx.arc(100, 250, 50, 0, 2 * Math.PI);
ctx.closePath();
ctx.arc(300, 250, 50, 0, 2 * Math.PI);
ctx.closePath();
ctx.rect(95,245,200,10);
ctx.clip('evenodd');
ctx.beginPath();
ctx.rect(5, 5, 400, 400);
ctx.fillStyle = 'rgba(255,0,0,1)';
ctx.fill();
</script>

result:
result:

desired result:
desired result:

wireman
  • 13
  • 3

1 Answers1

0

Using globalCompositeOperation

You can use it to cut out parts of the image ctx.globalCompositeOperation = "destination-out";

And to draw only to transparent parts of the image. ctx.globalCompositeOperation = "destination-over"

So rather than draw the background first, you draw the outer shape, then cut out what you need and then finaly draw the background behind everything.

Example

const ctx = canvas.getContext('2d');

// draw red box first
ctx.beginPath();
ctx.rect(5, 5, 400, 400)
ctx.fillStyle = "#F00";
ctx.fill();

// Cut out circles using globalCompositeOperation  "destination-out"
ctx.globalCompositeOperation = "destination-out";
ctx.fillStyle = "#000";
ctx.beginPath();
ctx.arc(100, 250, 50, 0, 2 * Math.PI);
ctx.closePath();
ctx.arc(300, 250, 50, 0, 2 * Math.PI);
ctx.closePath();
ctx.rect(95,245,200,10);
ctx.fill();

// Add background last using "destination-over";
ctx.globalCompositeOperation = "destination-over";
ctx.rect(0, 0,500, 500);
ctx.fillStyle = "#999";
ctx.fill();
<canvas id="canvas" width = "500" height="500" style="width:200px;height:200px;"></canvas>
Blindman67
  • 51,134
  • 11
  • 73
  • 136