Thursday, 23 February, 2017 UTC


Summary

Here, I will discuss how you can build a simple JavaScript Line Chart Library. Here we will try to make a line chart using HTML5 canvas. As it will be library so the code have to be easy for the other developers to use. The final product would look like this picture. I tried to keep this as simple as possible because thus you will understand the basics of the advanced javascript methodology. I hope you have intermediate javascript understanding. 
Intended Usage Example
Here is an example code what we want to achieve for others to use this library. Please read the comments. I will encourage you to write the code ( do not copy )
// Data for the LineChart
var data = {
    labels: ["Sandeep", "Pranay", "Tanmoy", "Sujit"],
    dataset: [15, 25, 13, 19]
};


// Making a chart instance
var chart = new VasChart("canvas");
chart.setData(data).draw();
Constructor Method
Now let’s build the main constructor method VasChart. This constructor will take one argument. The argument is actually CSS selector of the HTML5 canvas element.
var VasChart = function (elem) {
    // HTML5 canvas element
    this._elem = document.querySelector(elem);
    // Drawing data
    this._data = {};
    
    // Garb the context for drawing
    this._ctx = this._elem.getContext("2d");
    // Setting some behavior  of the context
    this._ctx.lineCap = "round";
    this._ctx.lineJoin = "round";
     
    // Keeping track of the height and width of the canvas
    this._height = this._elem.height;
    this._width = this._elem.width;

};
Here one thing to be noted that variable names are appended with a hyphen  ” _ “. We will append the hyphen to only those variables which will be used by the library itself. As it is a library for a line chart, we need reference for the origin, axis and the actual coordinates object of the data to be drawn. Let’s define them in the constructor method.
this._xAxis = {
        startPos: { x: null, y: null },
        endPos: { x: null, y: null },
        length: null
    };

    this._yAxis = {
        startPos: { x: null, y: null },
        endPos: { x: null, y: null },
        length: null
    };

    this._origin = {
        x: null,
        y: null
    };

    this._lineChartData = [];

    this._xPadding = null;
    this._yPadding = null;
    this._labelsCount = null;
Setting the line chart data
Now we need a method to set the data of the line chart. At the end of this method we will return ‘this’ to chain the methods.
VasChart.prototype.setData = function (data) {
    this._data = data;
    this._labelsCount = this._data.labels.length;
    //  We will return 'this' to chain the methods
    return this;
};
Set context origin to the Lower Left of the Canvas
If you have programmed for the HTML5 canvas, you will know that the 0,0 coordinates actually lives in the top left corner of the canvas. To make the 0,0 coordinates in the bottom left corner, we need this method. We are doing this to ease out our thinking process. Otherwise we need to map every point respect to the canvas.
VasChart.prototype._setContextOriginLowerLeft = function () {
    this._ctx.translate(0, this._height);
    this._ctx.scale(1, -1);
    return this;
}
Draw Line Method
We are making a line chart library so obviously we need a method to draw a line. This method will take two arguments which are essentially two points. We will use this helper method two draw all the lines.
VasChart.prototype._drawLine = function (start, end) {
    this._ctx.beginPath();
    this._ctx.moveTo(start.x, start.y);
    this._ctx.lineTo(end.x, end.y);
    this._ctx.stroke();
    return this;
};
Set origin of the graph and calculate axis properties
Now use this above method to draw our axis. But the problem here is that we need to perfectly calculate the starting and ending coordinates of the two axises. We also want to give padding in the bottom and left of the canvas. In this belew method, we will set our origin and the set the axis properly.
VasChart.prototype._setAxis = function () {
    // Setting the padding
    this._xPadding = Math.round(this._width * 0.1);
    this._yPadding = Math.round(this._height * 0.1);
    
    // Calculate the axis length
    this._xAxis.length = Math.round(this._width - this._xPadding);
    this._yAxis.length = Math.round(this._height - this._yPadding);
    
    // Set the origin coordinate 
    this._origin.x = this._width - this._xAxis.length;
    this._origin.y = this._height - this._yAxis.length;

    // Calculate the start and end position of the X Axis
    this._xAxis.startPos = this._origin;
    this._xAxis.endPos.x = this._width;
    this._xAxis.endPos.y = this._origin.y;

    // Calculate the start and end position of the Y Axis
    this._yAxis.startPos = this._origin;
    this._yAxis.endPos.x = this._origin.x;
    this._yAxis.endPos.y = this._height;

    return this;
};
Drawing the axis
Now we have properly set the axis. Let’s use our draw line method to draw the axis.
VasChart.prototype._drawAxis = function () {
    //Draw X axis
    this._drawLine(this._xAxis.startPos, this._xAxis.endPos);
    // Draw Y axis
    this._drawLine(this._yAxis.startPos, this._yAxis.endPos);
    return this;
};
Calculate the pixel coordinates from the line data
Let’s understand the problem here. We have our data in the form of key and value. We need to calculate the exact coordinates for the lines in the graph. For that reason, we need to map each data point into the pixel domain. Like if a point x ( x = 5 ) is defined in the domain [0 , 10] we will calculate the value of x in the provided domain [0, 100]. This is done by our _map method. We also need to calculate the max and min of the data points.
VasChart.prototype._map = function (x, in_min, in_max, out_min, out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
};

VasChart.prototype._getMax = function (arr) {
    return Math.max.apply(null, arr);
};


VasChart.prototype._getMin = function (arr) {
    return Math.min.apply(null, arr);
}
Build Line Chart Data Coordinates Array
By the help of the above method, we will loop through the dataset and calculate the exact data point coordinates respect to the canvas. We will save this points in one array. In the end, we will use this array to draw all the lines in the graph.
VasChart.prototype._buildLineChartData = function () {
    
    var xStep = this._xAxis.length / this._labelsCount;

    var initialXPoint = this._xPadding;
    var maxY = this._getMax(this._data.dataset);
    var minY = this._getMin(this._data.dataset);

    for (var i = 0; i < this._labelsCount; i++) {
        this._lineChartData.push({
            x: initialXPoint,
            y: this._map(this._data.dataset[i], minY, maxY, this._yPadding, this._height)
        });
        initialXPoint += xStep;
    }

};
The ultimate draw method
Now we will write the draw method, here will call our all necessary methods and draw the lines looping through that previously built array. Here we have scratched a little what you can achieve through vanilla js.
VasChart.prototype.draw = function () {
    this._setContextOriginLowerLeft(); // Important
    this._setAxis();
    this._drawAxis();
    this._buildLineChartData();

    for (var i = 0; i < this._labelsCount - 1; i++) {
        this._drawLine(this._lineChartData[i], this._lineChartData[i + 1]);

    }
};
Homework for you
I want you to write a method to perfectly write the labels just below the x axis. Please make a pull request after solving it. You can also add colors to the context. You can add any features you like. It is your own javascript line chart library. The whole project can be found in the github. Just clone it and use it.
If you have any questions, please let me know in the comments. Hope you like this article.
The post Learn to build JavaScript Canvas Line Chart in 2017 appeared first on Apply Head.