In a client project I had to draw by hand a quadratic Bézier curve, because the html5 canvas quadraticCurveTo does not return the information about the path drawn and I needed it.

Some basic explanation of a quadratic Bézier curve. You have a start point P1 , an end point P2 and a control point C . Both the x and y of each point on the path is dependant on t , which will vary from 0 to 1. t=0 at the begining of the curve and t=1 and the end of the curve.

You draw an imaginary line between P1 and C ( P1C line) and another one between C and P2 ( CP2 line). For each value of t , you mark an imaginary point on P1C and CP2 . The point on P1C is at t of the line, starting at P1 , and the point on the CP2 line is at t of the line, starting at C . Let's call those points C1 and C2 .

Then, you draw an imaginary line between C1 and C2 , and you mark a real point at t of the C1C2 line.

You repeat the procedure for every value of t , where t varies from 0 to 1. All the points you marked on the line C1C2 are showing the quadratic Bézier curve.

Here's a little animation I made to explain it better:

t = 0

You can have a look at the source for a complete understanding, but here's the important part, edited for clarity:

// constants

var CANVAS_WIDTH = 301 ;

var CANVAS_HEIGHT = 301 ;

var p1x = 20 ;

var p1y = 200 ;

var cx = 140 ;

var cy = 20 ;

var p2x = 280 ;

var p2y = 280 ;



// basic setup

var $t = $ ( '#bezier-example-1-t span' );



var animationCanvas = $ ( '#bezier-example-1 .animation' ). get ( 0 );

var animationContext = animationCanvas . getContext ( '2d' );

animationCanvas . width = CANVAS_WIDTH ;

animationCanvas . height = CANVAS_HEIGHT ;



var curveCanvas = $ ( '#bezier-example-1 .curve' ). get ( 0 );

var curveContext = curveCanvas . getContext ( '2d' );

curveCanvas . width = CANVAS_WIDTH ;

curveCanvas . height = CANVAS_HEIGHT ;

curveContext . strokeStyle = "#777" ;

curveContext . lineWidth = 2 ;

curveContext . beginPath ();

curveContext . moveTo ( p1x , p1y );

curveContext . stroke ();



setInterval ( updateDemo , 1000 / 30 );



var t = 0 ;

var d = 1 ; // direction



function updateDemo () { // called 30 times/second to animate

if ( t > 1 || t < 0 ) {

d *= - 1 ; // change direction

curveContext . clearRect ( 0 , 0 , CANVAS_WIDTH , CANVAS_HEIGHT );

curveContext . beginPath ();

}

t += 0.01 * d ; // continue moving

$t . html ( Math . round ( t * 100 ) / 100 );

// update values

var c1x = p1x + ( cx - p1x ) * t ;

var c1y = p1y + ( cy - p1y ) * t ;

var c2x = cx + ( p2x - cx ) * t ;

var c2y = cy + ( p2y - cy ) * t ;

var tx = c1x + ( c2x - c1x ) * t ;

var ty = c1y + ( c2y - c1y ) * t ;



animationContext . save ();

// clear old sketch

animationContext . clearRect ( 0 , 0 , CANVAS_WIDTH , CANVAS_HEIGHT );

// draw new line

animationContext . beginPath ();

animationContext . strokeStyle = '#aaa' ;

animationContext . lineWidth = 1 ;

animationContext . moveTo ( c1x , c1y );

animationContext . lineTo ( c2x , c2y );

animationContext . stroke ();

// draw points on lines

drawPoint ( animationContext , c1x , c1y , 2 , '#0f0' );

drawPoint ( animationContext , c2x , c2y , 2 , '#0f0' );

// draw point on curve

drawPoint ( animationContext , tx , ty , 3 , '#f0f' );

animationContext . restore ();



// draw the new Bezier curve segment

curveContext . lineTo ( tx , ty );

curveContext . stroke ();

}



The code is on Github.