Nice ellipse on a canvas?

后端 未结 3 912
感情败类
感情败类 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: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.

提交回复
热议问题