Thursday, January 15, 2009

ellipse and circle for canvas 2d context

These days I am working inside an ExtJS panel to create some sophisticated drawing stuff, and I discovered (too late ...) that there is almost nothing in canvas 2d context to draw circle or ellipse.

That's why I have extended Google excanvas library and/or native canvas 2d context prototype to let us create circles and ellipse in the same simple way we can create rectangles.

Here the extended proto:

(function(){
// Andrea Giammarchi - Mit Style License
var extend = {
// Circle methods
circle:function(aX, aY, aDiameter){
this.ellipse(aX, aY, aDiameter, aDiameter);
},
fillCircle:function(aX, aY, aDiameter){
this.beginPath();
this.circle(aX, aY, aDiameter);
this.fill();
},
strokeCircle:function(aX, aY, aDiameter){
this.beginPath();
this.circle(aX, aY, aDiameter);
this.stroke();
},
// Ellipse methods
ellipse:function(aX, aY, aWidth, aHeight){
var hB = (aWidth / 2) * .5522848,
vB = (aHeight / 2) * .5522848,
eX = aX + aWidth,
eY = aY + aHeight,
mX = aX + aWidth / 2,
mY = aY + aHeight / 2;
this.moveTo(aX, mY);
this.bezierCurveTo(aX, mY - vB, mX - hB, aY, mX, aY);
this.bezierCurveTo(mX + hB, aY, eX, mY - vB, eX, mY);
this.bezierCurveTo(eX, mY + vB, mX + hB, eY, mX, eY);
this.bezierCurveTo(mX - hB, eY, aX, mY + vB, aX, mY);
this.closePath();
},
fillEllipse:function(aX, aY, aWidth, aHeight){
this.beginPath();
this.ellipse(aX, aY, aWidth, aHeight);
this.fill();
},
strokeEllipse:function(aX, aY, aWidth, aHeight){
this.beginPath();
this.ellipse(aX, aY, aWidth, aHeight);
this.stroke();
}
};
for(var key in extend)
CanvasRenderingContext2D.prototype[key] = extend[key];
if(!this.G_vmlCanvasManager)
G_vmlCanvasManager = {init:function(){}, initElement:function(el){return el}};
})();


The last part is to obtain the same behavior with any browser and runtime create canvas:

var myCanvas = G_vmlCanvasManager.initElement(document.createElement("canvas"));


SImple and efficient? I hope so, since I spent more than a couple of minutes to be able to create a perfect circle via 1/4 of a rectangle (square ... but how could I remember the bloody constant to do that?) :P

P.S. I remind you that the simplest function to create a circle via a center is canvas.arc(x, y, radius, 0, Math.PI*2); and that this proto create a circle inside a specified square but ithout the same arc performances ( anyway, runtime rendering in IE and my personal version of excanvas even faster than FireFox 3 ... anybody interested? :-) )

Labels: , , ,

6 Comments:

Anonymous Anonymous said...

Thanks, but:

s/strokeCircle:function(aX, aY, aWidth, aHeight)/strokeCircle:function(aX, aY, aDiameter)

26 February, 2009 00:47  
Blogger Andrea Giammarchi said...

oops, cheers :)

26 February, 2009 10:08  
Anonymous Adam said...

Why not use arc(To) to draw circles, maybe its faster?

28 February, 2009 16:05  
Anonymous Anonymous said...

Yes, arc seems to be easier. And combining it with scale you'll got an ellipse.

03 March, 2010 07:30  
Blogger Lars said...

Here's the version I'm using now, which also can rotate the ellipse from its default axis alignment:


// draw ellipse
// r = radius of base circle
// w,h = ratio of ellipse width,height to r
// a = angle of rotation (radians) clockwise from orthogonal
function ellipse(ctx, x, y, r, w, h, a) {
ctx.beginPath();
ctx.save();
ctx.translate(x, y);
ctx.rotate(a);
ctx.scale(w, h);
ctx.arc(0, 0, r, 0, Math.PI * 2);
ctx.restore();
}

It works.

11 March, 2011 20:00  
Blogger Saranya SukumaR said...

Is there any similar function to draw a semicircle?

27 January, 2012 01:55  

Post a Comment

Links to this post:

Create a Link

<< Home