Bezier curves in HTML5 canvas

2017-02-16 by Senko Rašić

In web apps that allow users to freehand draw, an important technical limitation is the number of points the app can detect (usually through touchmove/mousemove) events. If the number of points is too small, a naive implementation which just draws straight line between them will show rough edges and look artificial.

If we use curves instead of straight lines, the result will be much more pleasant. The canvas drawing context provides methods for drawing quadratic and cubic Bezier curves. However, the implementation only draws the curve between two points, and requires extra control points.

A number of articles and tutorials online deal with this but the solutions they give usually go near but not neccessarily through the given points.

Let's try to come up with a better solution.

Theory

The challenge is to construct the curves between each two points so that the slope of both of the curves touching at each point is the same.

Any choice of slope will do, but for our purposes the easiest is to pick the slope that is parallel to the slope of the straight line connecting the previous and next points. The reasoning is that the line goes from the previous point, needs to curve "back" at our point to be able to reach the next point.

The second decision we need to make is how far out on the tangent to put the control points. This distance is proportional to the distance between previous and next points and another parameter usually called tension that describes how "tight" a corner is made. One-quarter (1/4) gives nice effects and is a common choice so we'll use that one.

The last remaining part is how to choose the control points for the first and last point since we have neither the tangent nor the distance. Here we'll cheat and use a midpoint between the endpoint (start or end point) and it's neighbour's control point.

As evident, there are a lot of wiggle-room here, and the correct parameters really depend on the desired effect. In this case we're primarily interested in seeing something that well approximates the curves written by hand, in cases we have less than ideal number of points.

A general discussion of Bezier curves in HTML5 and a bit more theory (and demos with more tweakable parameters!) are available in Rob Spencer's article.

Practice

When we translate the theory into code, here's the result (click on the canvas to add points, or click here clear the canvas.)

The code

If you'd like to use this in your own project, go ahead! The source is available on GitHub under an open source license. Contributions welcome!

Author
Senko Rašić
We’re small, experienced and passionate team of web developers, doing custom app development and web consulting.