Skip to content

Instantly share code, notes, and snippets.

@stevommmm
Created October 26, 2015 05:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stevommmm/7aba3e43fcabbb9f2840 to your computer and use it in GitHub Desktop.
Save stevommmm/7aba3e43fcabbb9f2840 to your computer and use it in GitHub Desktop.
basic time series graph

Basic canvas graphing

example

var Graph = function(canvasid, height, width, title, fontsize, maxlabels) {
this.canvas = document.getElementById(canvasid);
this.ctx = this.canvas.getContext("2d");
this.padding = [10, 60, 10, 10];
this.width = width || 1000;
this.height = height || 100;
this.title = title || "Time Series";
this.fontsize = fontsize || 11;
this.maxlabels = maxlabels || null;
this.data = [];
this.canvas.width = this.width + this.padding[0] + this.padding[2];
this.canvas.height = this.height + this.padding[1] + this.padding[3];
};
Graph.prototype.addPoint = function(d) {
if (typeof(d) === "number") {
this.data.push(d);
}
// We presume that we will be using a font size of 11px
if (this.data.length > this.width) {
this.data = this.data.splice(this.data.length - this.width, this.data.length);
}
};
Graph.prototype.addPoints = function(d) {
if (d instanceof Array) {
Array.prototype.push.apply(this.data, d);
}
if (this.data.length > this.width) {
this.data = this.data.splice(this.data.length - this.width, this.data.length);
}
};
Graph.prototype.w = function() {
return Math.floor(this.width / (this.data.length - 1));
};
Graph.prototype.h = function(h) {
var max = Math.max.apply(null, this.data);
var per = this.height / max;
return Math.floor(this.height - (h * per));
};
Graph.prototype.render = function() {
// Magic variables for label spacing
if (this.maxlabels === null) {
this.maxlabels = Math.floor(this.width / (this.fontsize));
}
this.ctx.font = this.fontsize + "px Courier New, Courier, monospace";
this.ctx.textAlign = 'end';
// Draw our graph, may contain more plot points than labels
this.ctx.beginPath();
this.ctx.strokeStyle = 'rgba(140, 40, 40, 0.2)';
this.ctx.lineCap = 'butt';
this.ctx.lineWidth = 2;
for(var i = 0; i < this.data.length; i++) {
var x = (i * this.w()) + this.padding[0];
var y = this.h(this.data[i]) + this.padding[1];
this.ctx.lineTo(x, y);
}
this.ctx.stroke();
// Draw our labels and their vertical strokes for visability
this.ctx.strokeStyle = 'rgba(140, 40, 40, 0.1)';
this.ctx.lineWidth = 1;
this.ctx.beginPath();
for(var i = 0; i < this.data.length; i++) {
var x = (i * this.w()) + this.padding[0];
var y = this.h(this.data[i]) + this.padding[1];
// If we limit labels don't draw them
var s = this.data.length / this.maxlabels;
if (Math.floor(i % s) && i !== this.data.length - 1) {
continue;
}
// Our height offset without the label length
this._drawDataLabel(this.data[i], i);
// Draw our vertical lines
this.ctx.moveTo(x, this.padding[1]);
this.ctx.lineTo(x, y - 10);
}
this.ctx.stroke();
this.ctx.fillStyle = 'rgba(140, 40, 40, 0.4)';
for(var i = 0; i < this.data.length; i++) {
var x = (i * this.w()) + this.padding[0];
var y = this.h(this.data[i]) + this.padding[1];
this._drawDataDot(x, y);
}
// Draw our graph title in the top padding space
this._drawGraphLabel(this.title);
};
Graph.prototype._drawDataDot = function(x, y) {
this.ctx.moveTo(x, y);
this.ctx.beginPath();
this.ctx.arc(x, y, 2, 0, 2 * Math.PI);
this.ctx.fill();
};
Graph.prototype._drawDataLabel = function(label, offset) {
var x = (offset * this.w()) + this.padding[0];
var w = this.ctx.measureText(label).width;
this.ctx.save();
this.ctx.fillStyle = 'rgb(0, 0, 0)';
this.ctx.translate(x, this.padding[1] - w - 10);
this.ctx.rotate(-90 * Math.PI / 180);
this.ctx.fillText(label, 0, 3);
this.ctx.restore();
};
Graph.prototype._drawGraphLabel = function(label) {
var x = (this.width / 2) + this.padding[0];
var w = this.ctx.measureText(label).width;
this.ctx.save();
this.ctx.font = (this.fontsize + 2) + "px bold Helvetica, Helvetica Neue, Arial";
this.ctx.textAlign = 'center';
this.ctx.fillStyle = 'rgb(0, 0, 0)';
this.ctx.translate(x, this.fontsize);
this.ctx.fillText(label, 0, 0);
this.ctx.restore();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment