Alex Rivera | Logout

How to fill the 'opposite' shape on canvas?

Asked 2011-06-07T20:46:26.957
40

Say I have a circle (an arc) on HTML5 canvas. I can just fill it like this:

ctx.arc(100, 100, 50, 0, 2 * Math.PI);
ctx.fill();

It works a treat. However, how can one fill the opposite area? Now it's white with a black circle, but I'd like it to be along the lines of the following image (on which white is the background color and black is the filling color):

opposite area

I know I could just use a black background and paint a white circle, but the background can be anything (all kinds of things have been drawn there before, so just swapping colors is not possible).

Another thing is that not the complete canvas should be filled, but rather a square with an circle canceled out.

I was thinking of a globalCompositeOperation but it does not seem to fit my needs as none of them act according to what I need.

So, how can I accomplish filling the 'opposite' area like in the example image?

Edit
Report

1 Answer

24

You can do that using another canvas as mask :

// This is the canvas where you want to draw
var canvas = document.getElementById('your-canvas');
var ctx = canvas.getContext('2d');

// I'll use a skyblue background that covers everything
// Just to demonstrate
ctx.fillStyle = "skyblue";
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Create a canvas that we will use as a mask
var maskCanvas = document.createElement('canvas');
// Ensure same dimensions
maskCanvas.width = canvas.width;
maskCanvas.height = canvas.height;
var maskCtx = maskCanvas.getContext('2d');

// This color is the one of the filled shape
maskCtx.fillStyle = "black";
// Fill the mask
maskCtx.fillRect(0, 0, maskCanvas.width, maskCanvas.height);
// Set xor operation
maskCtx.globalCompositeOperation = 'xor';
// Draw the shape you want to take out
maskCtx.arc(30, 30, 10, 0, 2 * Math.PI);
maskCtx.fill();

// Draw mask on the image, and done !
ctx.drawImage(maskCanvas, 0, 0);
<canvas id="your-canvas">

Demo here.

answered 2011-06-07T21:29:49.237

Your Answer