Skip to content

Instantly share code, notes, and snippets.

@sbrl sbrl/SmoothLine.js
Last active Jan 30, 2018

What would you like to do?
[SmoothLine.js] A class to aid the drawing of smooth lines. #es6 #module #microlibrary
"use strict";
**************************** ES6 Smooth Line Class ****************************
* v0.1
* A smooth line class built upon my earlier bezier curve and vector classes.
* Given a number of points (not all of which have to be specified at once),
* this class will add the appropriate lineTos to the given drawing context.
* This class was originally written on Codepen. Links:
* Codepen:
* Blog post: (coming soon!)
* This class depends on my earler bezier curve and vector classes. Links:
* Vector class:
* Bezier curve class:
* Bug reports can be made as a comment on this gist, or
* sent to <>. Alternatively, you can tweet
* me at @SBRLabs.
* Author: Starbeamrainbowlabs <>
* Changelog:
* v0.1: Initial revision.
class SmoothLine
this.points = [];
this.interpolatedPoints = [];
this.bezierCurves = [];
this.lastPointLength = -1;
* Adds one or more points to the smooth line.
* @param {Vector} point A single vector or an array of vectors to add onto the end of the smooth line.
if (Array.isArray(point))
* Internal. Interpolates THe given array of vectors once.
* @param {Vector[]} points The array of vectors to interpolate.
* @param {number} time The percentage between 0 and 1 at which to interpolate.
* @return {Vector[]} The interpolated vectors.
interpolateOnce(points, time)
// Input validation checks
if (time < 0 || time > 1)
throw new Error(`The time specified was out of bounds! It should be between 0 and 1, but a value of ${time} was provided.`);
if (!Array.isArray(points))
throw new Error("THe points provided are not in an array!");
if (points.length < 3)
throw new Error("A minimum of 3 points are required to draw a smooth line.");
var result = [];
// Loop over all the points, except the last one
for (let i = 0; i < points.length - 1; i++) {
// Find the difference between the current point and the next one along
// To get the vector of the line between 2 points, you do b - a for the points a and b.
let difference = points[i + 1].clone().subtract(points[i]);
// Multiply the line's vector by the time in order to extract a percentage along the line
// Add the first point on to put the vector back in the right place,
// and then add it to the interpolated pionts array.
// It's important to add the first control point on again here as we
// made the vector relative to 0 in order to perform the
// interpolation rather than relative to the first point on the line
// as it should be.
return result;
* Adds the smooth line to the path of the given canvas drawing context.
* @param {CanvasDrawingContext2D} context The drawing context to add the smooth line to.
* @param {number} segmentCount The number of segments that each bezier curve should have.
line(context, segmentCount)
if (this.points.length < 3)
throw new Error(`At least 3 points are required to draw a smooth line, but only ${this.points.length} points are currently specified.`);
if (this.lastPointLength !== this.points.length)
// Reset the bezier curve cache
this.bezierCurves = [];
this.interpolatedPoints = this.interpolateOnce(this.points, 0.5);
// Loop over every point except the frst & last ones
for (let i = 1; i < this.points.length - 1; i++)
let nextPointSet = [
this.interpolatedPoints[i - 1],
// If this is the first iteration, make the first point of the bezier curve the first point that we were given
if (i == 1)
nextPointSet[0] = this.points[0];
// If this is the last iteration, make the end point of the bezier curve the last point we were given
if (i == this.points.length - 2)
nextPointSet[2] = this.points[this.points.length - 1];
// The above 2 checks are needed to make sure that the smooth line starts and ends at the points that we were given
let nextBezier = new BezierCurve(nextPointSet);
// Spin through all the bezier curves and get them to add themselves to the current path
for (let i = 0; i < this.bezierCurves.length; i++)
this.bezierCurves[i].curve(context, segmentCount);
// Update the cached poits length
this.lastPointLength = this.points.length;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.