I want to clip an annulus (i.e. ring) from an image via javascripts canvas. I already have an approach but i think its too inelegant (and I really dont understand why this works, and why it doesnt just result in a smaller circle).
context.drawImage(imageObj, 0, 0, 500, 500);
//crop outer circle
context2.beginPath();
context2.arc(250, 250, 200, 0, 2 * Math.PI, false);
context2.closePath();
context2.clip();
//draw circle
context2.drawImage(canvas,0,0);
//crop inner circle
context2.beginPath();
context2.arc(250, 250, 100, 0, 2 * Math.PI, false);
context2.closePath();
context2.clip();
//clear context 2
context2.clearRect(0,0,500,500)
// finally draw annulus
context2.drawImage(canvas2,0,0);
is there a better way to do this?
This does work because clipping areas called by clip
method do stack.
IMO, this is indeed not the best way to do it, as you definitely need to call ctx.save();
before clipping and ctx.restore()
afterward, which are really heavy methods.
My preferred way is to use compositing :
var ctx = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(imageObj, 0, 0, 500, 500);
// keep only the outer circle
ctx.globalCompositeOperation = 'destination-in';
ctx.beginPath();
ctx.arc(250, 250, 200, 0, 2 * Math.PI, false);
ctx.fill();
// remove the inner one
ctx.globalCompositeOperation = 'destination-out';
ctx.beginPath();
ctx.arc(250, 250, 100, 0, 2 * Math.PI, false);
ctx.fill();
// reset gCO
ctx.globalCompositeOperation = 'source-over';
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
<canvas id="canvas" width="500" height="500"></canvas>