Nice ellipse on a canvas?

后端 未结 3 863
感情败类
感情败类 2020-12-11 23:26

Is it possible to create ovals/ellipses with nicer strokes that have not that \"blurred\" border similar to:

  • http://www.html5canvastutorials.com/kineticjs/html
相关标签:
3条回答
  • 2020-12-11 23:37

    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.

    0 讨论(0)
  • 2020-12-11 23:38

    ! 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 :

    • draw border in a temp canvas
    • getImageData of the canvas
    • get a Uint32Array or Uint8Array view on underlying data
    • loop linearly within array : if value > threshold set it to border color
    • draw the fill of the ellipse on target canvas
    • putImageData on target canvas.

    Which one ?

    • Second one does not require globalCompositeOperation to work.
      But on most browsers (all ?) get/put ImageData are slow as hell, this fact
      alone might invalidate this solution.
      The nice thing is you can precisely decide how to un-antialias.

    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.

    0 讨论(0)
  • 2020-12-11 23:46

    Yes, you can! Here's the result of calling context.stroke() 25 times instead of just once:

    non-blurry ellipse

    For comparison, here's the original:

    blurry ellipse

    0 讨论(0)
提交回复
热议问题