How to anti-alias clip() edges in html5 canvas under Chrome Windows? How to anti-alias clip() edges in html5 canvas under Chrome Windows? google-chrome google-chrome

How to anti-alias clip() edges in html5 canvas under Chrome Windows?


If you're doing complex, layered drawing, you can use globalCompositeOperation to emulate clipping in a second, scratch canvas. You can then use drawImage to copy the scratch canvas back into the original canvas. I can't guarantee the performance of this approach, but it's the only way I know to get what you want.

//set-up - probably only needs to be done oncevar scratchCanvas = document.createElement('canvas');scratchCanvas.width = 100;scratchCanvas.height = 100;var scratchCtx = scratchCanvas.getContext('2d');//drawing codescratchCtx.clearRect(0, 0, scratchCanvas.width, scratchCanvas.height);scratchCtx.globalCompositeOperation = 'source-over'; //default//Do whatever drawing you want. In your case, draw your image.scratchCtx.drawImage(imageToCrop, ...);//As long as we can represent our clipping region as a single path, //we can perform our clipping by using a non-default composite operation.//You can think of destination-in as "write alpha". It will not touch//the color channel of the canvas, but will replace the alpha channel.//(Actually, it will multiply the already drawn alpha with the alpha//currently being drawn - meaning that things look good where two anti-//aliased pixels overlap.)////If you can't represent the clipping region as a single path, you can//always draw your clip shape into yet another scratch canvas.scratchCtx.fillStyle = '#fff'; //color doesn't matter, but we want full opacityscratchCtx.globalCompositeOperation = 'destination-in';scratchCtx.beginPath();scratchCtx.arc(50, 50, 50, 0, 2 * Math.PI, true);scratchCtx.closePath();scratchCtx.fill();//Now that we have a nice, cropped image, we can draw it in our//actual canvas. We can even draw it over top existing pixels, and//everything will look great!ctx.drawImage(scratchCanvas, ...);

The reason that we do this in a scratch canvas is that destination-in is a pretty destructive operation. If you had already drawn some things into the main canvas (perhaps you put down a nice gradient in the background), and then wanted to draw a clipped image, the clipping circle would also clip out everything you had already drawn. Of course, if your particular situation is simpler (maybe ALL you want to draw is a clipped image), then you can forego the scratch canvas.

You can play around with the different clipping modes on my demo page. The bottom row (with the gradients) is not too useful to you, but the top row (with the circle and square) is much more relevant.

edit

Whoops, I accidentally forked your JSFiddle to demonstrate the technique.


My fix for this is to draw a thin (2px) white stroke at the same radius after drawing the image. It covers up the aliasing nicely and looks fine across browsers.


I came across the same issue with Chrome and clip().

In my circumstance I achieved better browser compatibility by setting the canvas globalCompositeOperation.

context.globalCompositeOperation = 'source-atop';

So draw your shape, a circle in this case. Then switch to 'source-atop' and draw your kitten image.

Note, this is a quick fix for basic drawing and assumes a blank canvas. Previous canvas drawing will affect your clip.