Is it possible to create ovals/ellipses with nicer strokes that have not that \"blurred\" border similar to:
The short answer is no, sorry!
The specification does not comment on the anti-aliasing methods (or not) that browsers must use, so it will be disparate between browsers. Different editions of Chrome (especially if you use chrome beta or developer channel) flip flop on this all the time.
Some talk of codifying this in the specification has occurred before, but no action has been taken, except for images where there's now an option to turn off image smoothing (the context's imageSmoothingEnabled
property). This in no way applies to paths, though.
One solution that unfortunately will only work in the most narrow of circumstances: If your ellipses are fixed, is to create them in Firefox (arguably the browser with the smoothest anti aliasing) and generate images from them, then draw with images on all the browsers.
In short, if you want pixel-identical shapes across all browsers, you'll have to use images, there is currently no other way.
! you can do it ! by doing post-processing :
1) Using globalCompositeOperation :
Edit :
yes, but no : on Chrome at least, 'destination-in' does not
match the specifications : the source is used to compute destination
color, so we cannot have single color from a shaded one.
( i did a try on JSBin : http://jsbin.com/ecipiq/4/ )
OR
2) Using getImageData and performance Array :
Which one ?
Other StackOverflow members might have insight on all this.
Any of those solution will be much faster than a hand-written non-aliased ellipse function.
usefull link for first solution :
http://www.html5rocks.com/en/tutorials/webgl/typed_arrays/
Remarks to get you started faster :
You can get a UInt32Array view on your ImageData with :
var myGetImageData = myTempCanvas.getImageData(0,0,sizeX, sizeY);
sourceBuffer32 = new UInt32Array(myGetImageData.data.buffer);
then sourceBuffer32[i] contains Red, Green, Blue, and transparency packed into one unsigned 32 bit int. Compare it to 0 to know if pixel is non-black ( != (0,0,0,0) )
OR you can be more precise with a Uint8Array view :
var myGetImageData = myTempCanvas.getImageData(0,0,sizeX, sizeY);
sourceBuffer8 = new Uint8Array(myGetImageData.data.buffer);
If you deal only with shades of grey, then R=G=B, so watch for
sourceBuffer8[4*i]>Threshold
and you can set the i-th pixel to black in one time using the UInt32Array view :
sourceBuffer32[i]=(255<<24)||(255<<16)||(255<<8);
You'll surely be able to figure out how to deal with other colors than grey/black out of this example.
Yes, you can! Here's the result of calling context.stroke()
25 times instead of just once:
For comparison, here's the original: