Bezier and Quadratic Curve Using Canvas in HTML5

Bezier and Quadratic Curve in HTML5

 
Lines can be defined using three methods; they are:
  • Straight line It is drawn by specifying the x and y coordinates of the line starting and ending points.
  • Quadratic curve It is drawn by specifying the x and y coordinates for the starting point, ending point and a single control point. The relationship of the control point to the starting and ending points establishes the curvature of the line.
  • Bezier curve It is drawn by specifying the x and y coordinates for the starting point, ending point and two control points. The second control point provides finer control over the shape of the curve.  It allows for more complex shapes to be drawn. Shapes such as s-curves and the loop shown in the image to the left.  

Browser Supporting Bezier and Quardratic Curve

 
Internet Explorer 9, Firefox, Opera, Chrome, and Safari support both the bezierCurveTo() and quadraticCurveTo() method.
 
Note: Internet Explorer 8 and earlier versions, do not support the <canvas> element.
 

Bezier Curve

 
The bezierCurveTo() function draws a cubic Bezier curve from one point to another.
 
In order to draw the curve we require six arguments:
  • The x-coordinate of the first Bézier control point.
  • The y-coordinate of the first Bézier control point.
  • The x-coordinate of the second Bézier control point.
  • The y-coordinate of the second Bézier control point.
  • The x-coordinate of the point to add to the current path.
  • The y-coordinate of the point to add to the current path.
Bezier curves can be styled with the following properties:
  1. lineWidth
  2. strokeStyle
  3. lineCap  
The two little dots on the canvas are the control points that I have drawn to show you where they are. They are not drawn as part of the curve.  
Note: A cubic Bézier curve must include three points. The first two points are control points that are used in the cubic Bézier calculation and the last point is the ending point for the curve. The first point on the curve is the last point in the existing current subpath. If a path does not exist, use the "beginPath" and "moveTo" methods to create a starting point.
 

Syntax of Bezier Curve in HTML5

 
The syntax of Bezier Curve is:
  1. <script>  
  2. context.bezierCurveTo(controlX1, controlY1, controlX2, controlY2, endX, endY);  
  3. </script> 

Methods needed to draw the Bezier Curve

 
Method Description
beginPath() resets the current path.
moveTo(x,y) creates a new subpath with the given point.
closePath() marks the current subpath as closed, and starts a new subpath with a point the same as the start and end of the newly closed subpath.
fill() fills the subpaths with the current fill style.
stroke() strokes the subpaths with the current stroke style.
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) adds the given point to the current path, connected to the previous one by a cubic Bezier curve with the given control points.
 
The x and y parameters are the coordinates of the end point. cp1x and cp1y are the coordinates of the first control point, and cp2x and cp2y are the coordinates of the second control point.
 

Quadratic Curve

 
The "quadraticCurveTo()" function draws a quadratic Bezier curve from one point to another. The curve is controlled by a single control point.
Quadratic curves are defined by the context point, a control point, and an ending point.
 
In order to draw the curve we require six arguments:
  • The x-coordinate of the Bézier control point.
  • The y-coordinate of the Bézier control point.
  • The x-coordinate of the point to add to the current path.
  • The y-coordinate of the point to add to the current path.
Quadratic curves can be styled with thefollowing properties:
  1. lineWidth
  2. strokeStyle
  3. lineCap  
The little dot on the canvas is the control point that I have drawn there. It is not part of the curve normally.
 
The context point is defined by the "moveTo()"method. Moving the control point farther away from the context point and the ending point will create sharper curves, and moving the control point closer to the context point and the ending point will create broader curves. 
 

Syntax of Quadratic Curve in HTML5

 
The syntax of the Quadratic Curve is:
  1. <script>  
  2.         context.quadraticCurveTo(controlX, controlY, endX, endY);  
  3. </script> 
Methods needed to draw the Quadratic Curve
 
Method Description
beginPath() resets the current path.
moveTo(x,y) creates a new subpath with the given point.
closePath() marks the current subpath as closed, and starts a new subpath with a point the same as the start and end of the newly closed subpath.
fill() fills the subpaths with the current fill style.
stroke() strokes the subpaths with the current stroke style.
quadraticCurveTo(cpx, cpy, x, y) adds the given point to the current path, connected to the previous one by a quadratic Bezier curve with the given control point.
 
The x and y are the coordinates of the end point and cpx and cpy are the coordinates of the control point.
 

Difference between Bezier and Quadratic Curve

 
A cubic Bezier curve has 2 control points, whereas the quadratic Bezier curve only has 1 control point.
 
Cubic Bezier curves - 3rd degree curves - to fully define such a curve, one will need to specify 4 points:
  • two anchor points (P1 and P2) - the curve starts and, respectively, ends in these points
  • two control points (C1 and C2) - the control points influence how the "fast" the curve "leave" its ends
Anyone that used a vectorial drawing application (such as Adobe Illustrator, Corel Draw or Macromedia Freehand) will recognize a cubic Bezier curve in the applet on the left.
 
Note: Internet Explorer 8 and earlier versions, do not support the <canvas> element.
 
Quadratic Curve - 2nd-degree curve - is defined in a similar way as the cubic one, but requires a single control point.
 
The quadratic Bezier curves are used by the Macromedia Flash and in encoding/rendering TrueType fonts.
 
Example showing Bezier Curve and Quadratic Curve
  1. <!DOCTYPE html>  
  2.    
  3. <html lang="en" xmlns="http://www.w3.org/1999/xhtml">  
  4. <head>  
  5.     <meta charset="utf-8" />  
  6.     <title></title>  
  7.     <style>  
  8.         body {  
  9.             margin: 0px;  
  10.             padding: 0px;  
  11.         }  
  12.     </style>  
  13.     <script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.3.3-beta.js"></script>  
  14.     <script>  
  15.         function updateDottedLines(layer) {  
  16.             var q = layer.quad;  
  17.             var b = layer.bezier;  
  18.    
  19.             var quadLine = layer.get('#quadLine')[0];  
  20.             var bezierLine = layer.get('#bezierLine')[0];  
  21.    
  22.             quadLine.setPoints([q.start.attrs.x, q.start.attrs.y, q.control.attrs.x, q.control.attrs.y, q.end.attrs.x, q.end.attrs.y]);  
  23.    
  24.             bezierLine.setPoints([b.start.attrs.x, b.start.attrs.y, b.control1.attrs.x, b.control1.attrs.y, b.control2.attrs.x, b.control2.attrs.y, b.end.attrs.x, b.end.attrs.y]);  
  25.             layer.draw();  
  26.         }  
  27.         function buildAnchor(layer, curveLayer, x, y) {  
  28.             var anchor = new Kinetic.Circle({  
  29.                 x: x,  
  30.                 y: y,  
  31.                 radius: 20,  
  32.                 stroke: '#666',  
  33.                 fill: '#ddd',  
  34.                 strokeWidth: 2,  
  35.                 draggable: true  
  36.             });  
  37.    
  38.             anchor.on('mouseover'function () {  
  39.                 document.body.style.cursor = 'pointer';  
  40.                 this.setStrokeWidth(4);  
  41.                 layer.draw();  
  42.             });  
  43.             anchor.on('mouseout'function () {  
  44.                 document.body.style.cursor = 'default';  
  45.                 this.setStrokeWidth(2);  
  46.                 layer.draw();  
  47.             });  
  48.    
  49.             anchor.on('dragend'function () {  
  50.                 drawCurves(curveLayer.getCanvas(), layer.quad, layer.bezier);  
  51.                 updateDottedLines(layer);  
  52.             });  
  53.    
  54.             layer.add(anchor);  
  55.             return anchor;  
  56.         }  
  57.         function drawCurves(canvas, quad, bezier) {  
  58.             canvas.clear();  
  59.             var context = canvas.getContext();  
  60.    
  61.             // draw quad  
  62.             context.beginPath();  
  63.             context.moveTo(quad.start.attrs.x, quad.start.attrs.y);  
  64.             context.quadraticCurveTo(quad.control.attrs.x, quad.control.attrs.y, quad.end.attrs.x, quad.end.attrs.y);  
  65.             context.strokeStyle = 'red';  
  66.             context.lineWidth = 4;  
  67.             context.stroke();  
  68.    
  69.             // draw bezier  
  70.             context.beginPath();  
  71.             context.moveTo(bezier.start.attrs.x, bezier.start.attrs.y);  
  72.             context.bezierCurveTo(bezier.control1.attrs.x, bezier.control1.attrs.y, bezier.control2.attrs.x, bezier.control2.attrs.y, bezier.end.attrs.x, bezier.end.attrs.y);  
  73.             context.strokeStyle = 'blue';  
  74.             context.lineWidth = 4;  
  75.             context.stroke();  
  76.         }  
  77.    
  78.         window.onload = function () {  
  79.             var stage = new Kinetic.Stage({  
  80.                 container: 'container',  
  81.                 width: 578,  
  82.                 height: 200  
  83.             });  
  84.    
  85.    
  86.             var layer = new Kinetic.Layer();  
  87.    
  88.             var curveLayer = new Kinetic.Layer();  
  89.    
  90.             var quadLine = new Kinetic.Line({  
  91.                 dashArray: [10, 10, 0, 10],  
  92.                 strokeWidth: 3,  
  93.                 stroke: 'black',  
  94.                 lineCap: 'round',  
  95.                 id: 'quadLine',  
  96.                 opacity: 0.3,  
  97.                 points: [0, 0]  
  98.             });  
  99.    
  100.             var bezierLine = new Kinetic.Line({  
  101.                 dashArray: [10, 10, 0, 10],  
  102.                 strokeWidth: 3,  
  103.                 stroke: 'black',  
  104.                 lineCap: 'round',  
  105.                 id: 'bezierLine',  
  106.                 opacity: 0.3,  
  107.                 points: [0, 0]  
  108.             });  
  109.    
  110.             // add dotted line connectors  
  111.             layer.add(quadLine);  
  112.             layer.add(bezierLine);  
  113.    
  114.             layer.quad = {  
  115.                 start: buildAnchor(layer, curveLayer, 60, 30),  
  116.                 control: buildAnchor(layer, curveLayer, 240, 110),  
  117.                 end: buildAnchor(layer, curveLayer, 80, 160)  
  118.             };  
  119.    
  120.             layer.bezier = {  
  121.                 start: buildAnchor(layer, curveLayer, 280, 20),  
  122.                 control1: buildAnchor(layer, curveLayer, 530, 40),  
  123.                 control2: buildAnchor(layer, curveLayer, 480, 150),  
  124.                 end: buildAnchor(layer, curveLayer, 300, 150)  
  125.             };  
  126.    
  127.             stage.getDragLayer().beforeDraw(function () {  
  128.                 drawCurves(curveLayer.getCanvas(), layer.quad, layer.bezier);  
  129.                 updateDottedLines(layer);  
  130.             });  
  131.    
  132.             stage.on('mouseout'function () {  
  133.                 layer.draw();  
  134.             });  
  135.    
  136.             stage.add(curveLayer);  
  137.             stage.add(layer);  
  138.    
  139.             drawCurves(curveLayer.getCanvas(), layer.quad, layer.bezier);  
  140.             updateDottedLines(layer);  
  141.    
  142.         };  
  143.    
  144.     </script>  
  145. </head>  
  146. <body onmousedown="return false;">  
  147.     <h1>Bezier and Quadratic Curve</h1>  
  148.     <div id="container"></div>  
  149. </body>  
  150. </html> 
Output
 
Originally we get
 
curve1.jpg
 
On moving the mouse we get
 
curve2.jpg
 
Finally again moving mouse we get
 
curve3.jpg