HTML5 Game - Chart Line Chart

Plotting data points with a line chart

Line charts shows the data trends.

The following code create a configurable Line Chart class.

It takes in an array of data elements and plots each point while connecting the points with line segments.

Demo

ResultView the demo in separate window

<!DOCTYPE HTML>
<html>
    <head>
        <script>
class LineChart{/*from  w  w  w  .  j  a v  a 2  s  .c  o  m*/
   constructor(config){//from   www.  ja  va2s  . c  om
    this.canvas = document.getElementById(config.canvasId);
    this.minX = config.minX;
    this.minY = config.minY;
    this.maxX = config.maxX;
    this.maxY = config.maxY;
    this.unitsPerTickX = config.unitsPerTickX;
    this.unitsPerTickY = config.unitsPerTickY;
    
    this.padding = 10;
    this.tickSize = 10;
    this.axisColor = "#555";
    this.pointRadius = 5;
    this.font = "12pt Calibri";

    this.fontHeight = 12;
    
    // relationships   
    this.context = this.canvas.getContext("2d");
    this.rangeX = this.maxX - this.minY;
    this.rangeY = this.maxY - this.minY;
    this.numXTicks = Math.round(this.rangeX / this.unitsPerTickX);
    this.numYTicks = Math.round(this.rangeY / this.unitsPerTickY);
    this.x = this.getLongestValueWidth() + this.padding * 2;
    this.y = this.padding * 2;
    this.width = this.canvas.width - this.x - this.padding * 2;
    this.height = this.canvas.height - this.y - this.padding - this.fontHeight;
    this.scaleX = this.width / this.rangeX;
    this.scaleY = this.height / this.rangeY;
    
    // draw x y axis and tick marks
    this.drawXAxis();
    this.drawYAxis();
}

getLongestValueWidth(){
    this.context.font = this.font;
    let longestValueWidth = 0;
    for (let n = 0; n <= this.numYTicks; n++) {
        let value = this.maxY - (n * this.unitsPerTickY);
        longestValueWidth = Math.max(longestValueWidth, this.context.measureText(value).width);
    }
    return longestValueWidth;
}
drawXAxis(){
    let context = this.context;
    context.save();
    context.beginPath();
    context.moveTo(this.x, this.y + this.height);
    context.lineTo(this.x + this.width, this.y + this.height);
    context.strokeStyle = this.axisColor;
    context.lineWidth = 2;
    context.stroke();
    
    // draw tick marks
    for (let n = 0; n < this.numXTicks; n++) {
        context.beginPath();
        context.moveTo((n + 1) * this.width / this.numXTicks + this.x, this.y + this.height);
        context.lineTo((n + 1) * this.width / this.numXTicks + this.x, this.y + this.height - this.tickSize);
        context.stroke();
    }
    
    // draw labels
    context.font = this.font;
    context.fillStyle = "black";
    context.textAlign = "center";
    context.textBaseline = "middle";
    
    for (let n = 0; n < this.numXTicks; n++) {
        let label = Math.round((n + 1) * this.maxX / this.numXTicks);
        context.save();
        context.translate((n + 1) * this.width / this.numXTicks + this.x, this.y + this.height + this.padding);
        context.fillText(label, 0, 0);
        context.restore();
    }
    context.restore();
}

drawYAxis(){
    let context = this.context;
    context.save();
    context.save();
    context.beginPath();
    context.moveTo(this.x, this.y);
    context.lineTo(this.x, this.y + this.height);
    context.strokeStyle = this.axisColor;
    context.lineWidth = 2;
    context.stroke();
    context.restore();
    
    // draw tick marks
    for (let n = 0; n < this.numYTicks; n++) {
        context.beginPath();
        context.moveTo(this.x, n * this.height / this.numYTicks + this.y);
        context.lineTo(this.x + this.tickSize, n * this.height / this.numYTicks + this.y);
        context.stroke();
    }
    
    // draw values
    context.font = this.font;
    context.fillStyle = "black";
    context.textAlign = "right";
    context.textBaseline = "middle";
    
    for (let n = 0; n < this.numYTicks; n++) {
        let value = Math.round(this.maxY - n * this.maxY / this.numYTicks);
        context.save();
        context.translate(this.x - this.padding, n * this.height / this.numYTicks + this.y);
        context.fillText(value, 0, 0);
        context.restore();
    }
    context.restore();
}

drawLine(data, color, width){
    let context = this.context;
    context.save();
    this.transformContext();
    context.lineWidth = width;
    context.strokeStyle = color;
    context.fillStyle = color;
    context.beginPath();
    context.moveTo(data[0].x * this.scaleX, data[0].y * this.scaleY);
    
    for (let n = 0; n < data.length; n++) {
        let point = data[n];
        
        // draw segment
        context.lineTo(point.x * this.scaleX, point.y * this.scaleY);
        context.stroke();
        context.closePath();
        context.beginPath();
        context.arc(point.x * this.scaleX, point.y * this.scaleY, this.pointRadius, 0, 2 * Math.PI, false);
        context.fill();
        context.closePath();
        
        // position for next segment
        context.beginPath();
        context.moveTo(point.x * this.scaleX, point.y * this.scaleY);
    }
    context.restore();
}

transformContext(){
    let context = this.context;
    
    // move context to center of canvas
    this.context.translate(this.x, this.y + this.height);
    
    // invert the y scale so that that increments
    // as you move upwards
    context.scale(1, -1);
}
}
window.onload = function(){
    let myLineChart = new LineChart({
        canvasId: "myCanvas",
        minX: 0,
        minY: 0,
        maxX: 140,
        maxY: 100,
        unitsPerTickX: 10,
        unitsPerTickY: 10
    });
    
    let data = [{
        x: 10,
        y: 80
    }, {
        x: 20,
        y: 10
    }, {
        x: 40,
        y: 30
    }, {
        x: 60,
        y: 80
    }, {
        x: 80,
        y: 100
    }, {
        x: 100,
        y: 5
    }, {
        x: 120,
        y: 5
    }, {
        x: 140,
        y: 100
    }];
    
    myLineChart.drawLine(data, "blue", 3);
    
    data = [{
        x: 20,
        y: 15
    }, {
        x: 40,
        y: 50
    }, {
        x: 60,
        y: 35
    }, {
        x: 80,
        y: 10
    }, {
        x: 100,
        y: 100
    }, {
        x: 120,
        y: 20
    }, {
        x: 140,
        y: 35
    }];
    
    myLineChart.drawLine(data, "red", 3);
};
        </script>
    </head>
    <body>
<canvas id="myCanvas" width="600" height="300" style="border:1px solid black;">
</canvas>
    </body>
</html>