The issue I have is very straightforward. This is a variation of the "How can I draw a hole in a shape?" question, to which the classic answer is "Simply draw both shapes in the same path, but draw the solid clockwise and the "hole" counterclockwise." That's great but the "hole" I need is often a compound shape, consisting of multiple circles.
Visual description: http://i.imgur.com/9SuMSWT.png.
jsfiddle: http://jsfiddle.net/d_panayotov/44d7qekw/1/
context = document.getElementsByTagName('canvas')[0].getContext('2d');
// green background
context.fillStyle = "#00FF00";
context.fillRect(0,0,context.canvas.width, context.canvas.height);
context.fillStyle = "#000000";
context.globalAlpha = 0.5;
//rectangle
context.beginPath();
context.moveTo(0, 0);
context.lineTo(context.canvas.width, 0);
context.lineTo(context.canvas.width, context.canvas.height);
context.lineTo(0, context.canvas.height);
//first circle
context.moveTo(context.canvas.width / 2 + 20, context.canvas.height / 2);
context.arc(context.canvas.width / 2 + 20, context.canvas.height / 2, 50, 0, Math.PI*2, true);
//second circle
context.moveTo(context.canvas.width / 2 - 20, context.canvas.height / 2);
context.arc(context.canvas.width / 2 - 20, context.canvas.height / 2, 50, 0, Math.PI*2, true);
context.closePath();
context.fill();
EDIT:
Multiple solutions have been proposed and I feel that my question has been misleading. So here's more info: I need the rectangle area to act as a shade. Here's a screenshot from the game I'm making (hope this is not against the rules): http://i.imgur.com/tJRjMXC.png.
- the rectangle should be able to have alpha less than 1.0.
- the contents, displayed in the "holes" are whatever is drawn on the canvas before applying the shade.
@markE:
- Alternatively...to "knockout" (erase) the double-circles... - "destination-out" replaces the canvas content with the set background. http://jsfiddle.net/d_panayotov/ab21yfgd/ - The holes are blue instead of green.
- On the other hand... - "source-atop" requires content to be drawn after defining the clipping mask. This in my case would be inefficient (Light is drawn as concentric circles, shaded area still visible).
@hobberwickey: That's a static background, not actual canvas content. I can however use clip() the same way I would use "source-atop" but that would be inefficient.
The solution that I have implemented right now: http://jsfiddle.net/d_panayotov/ewdyfnj5/. I'm simply drawing the clipped rectangle (in an in-memory canvas) over the main canvas content. Is there a faster/better solution?