Last active
August 29, 2015 14:21
-
-
Save samarpanda/d035b919cee62f32d811 to your computer and use it in GitHub Desktop.
Line graph using HTML5 Canvas
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//http://jsbin.com/bajebo/2/edit?output | |
var CanvasChart = function() { | |
var ctx; | |
var margin = { | |
top: 40, | |
left: 75, | |
right: 0, | |
bottom: 75 | |
}; | |
var chartHeight, chartWidth, yMax, xMax, data; | |
var maxYValue = 0; | |
var ratio = 0; | |
var renderType = { | |
lines: 'lines', | |
points: 'points' | |
}; | |
var render = function(canvasId, dataObj) { | |
data = dataObj; | |
getMaxDataYValue(); | |
var canvas = document.getElementById(canvasId); | |
chartHeight = 600; //canvas.attr('height'); | |
chartWidth = 800; //canvas.attr('width'); | |
xMax = chartWidth - (margin.left + margin.right); | |
yMax = chartHeight - (margin.top + margin.bottom); | |
ratio = yMax / maxYValue; | |
ctx = canvas.getContext("2d"); | |
renderChart(); | |
} | |
function getMaxDataYValue() { | |
maxYValue = 308.7; | |
} | |
var renderChart = function() { | |
renderBackground(); | |
renderText(); | |
renderLinesAndLabels(); | |
//render data based upon type of renderType(s) that client supplies | |
if (data.renderTypes == undefined || data.renderTypes == null) data.renderTypes = [renderType.lines]; | |
for (var i = 0; i < data.renderTypes.length; i++) { | |
renderData(data.renderTypes[i]); | |
} | |
} | |
var renderBackground = function() { | |
var lingrad = ctx.createLinearGradient(margin.left, margin.top, xMax - margin.right, yMax); | |
lingrad.addColorStop(0.0, '#D4D4D4'); | |
lingrad.addColorStop(0.2, '#fff'); | |
lingrad.addColorStop(0.8, '#fff'); | |
lingrad.addColorStop(1, '#D4D4D4'); | |
ctx.fillStyle = lingrad; | |
ctx.fillRect(margin.left, margin.top, xMax - margin.left, yMax - margin.top); | |
ctx.fillStyle = 'black'; | |
} | |
var renderText = function renderText() { | |
var labelFont = (data.labelFont != null) ? data.labelFont : '20pt Arial'; | |
ctx.font = labelFont; | |
ctx.textAlign = "center"; | |
//Title | |
var txtSize = ctx.measureText(data.title); | |
ctx.fillText(data.title, (chartWidth / 2), (margin.top / 2)); | |
//X-axis text | |
txtSize = ctx.measureText(data.xLabel); | |
ctx.fillText(data.xLabel, margin.left + (xMax / 2) - (txtSize.width / 2), yMax + (margin.bottom / 1.2)); | |
//Y-axis text | |
ctx.save(); | |
ctx.rotate(-Math.PI / 2); | |
ctx.font = labelFont; | |
ctx.fillText(data.yLabel, (yMax / 2) * -1, margin.left / 4); | |
ctx.restore(); | |
} | |
var renderLinesAndLabels = function renderLinesAndLabels() { | |
//Vertical guide lines | |
var yInc = yMax / data.dataPoints.length; | |
var yPos = 0; | |
var yLabelInc = (maxYValue * ratio) / data.dataPoints.length; | |
var xInc = xMax / data.dataPoints.length; | |
var xPos = margin.left; | |
for (var i = 0; i < data.dataPoints.length; i++) { | |
yPos += (i == 0) ? margin.top : yInc; | |
//Draw horizontal lines | |
drawLine(margin.left, yPos, xMax, yPos, '#E8E8E8'); | |
//y axis labels | |
ctx.font = (data.dataPointFont != null) ? data.dataPointFont : '10pt Calibri'; | |
var txt = Math.round(maxYValue - ((i == 0) ? 0 : yPos / ratio)); | |
var txtSize = ctx.measureText(txt); | |
ctx.fillText(txt, margin.left - ((txtSize.width >= 14) ? txtSize.width : 10) - 7, yPos + 4); | |
//x axis labels | |
txt = data.dataPoints[i].x; | |
txtSize = ctx.measureText(txt); | |
ctx.fillText(txt, xPos, yMax + (margin.bottom / 3)); | |
xPos += xInc; | |
} | |
//Vertical line | |
drawLine(margin.left, margin.top, margin.left, yMax, 'black'); | |
//Horizontal Line | |
drawLine(margin.left, yMax, xMax, yMax, 'black'); | |
} | |
var drawLine = function drawLine(startX, startY, endX, endY, strokeStyle, lineWidth) { | |
if (strokeStyle != null) ctx.strokeStyle = strokeStyle; | |
if (lineWidth != null) ctx.lineWidth = lineWidth; | |
ctx.beginPath(); | |
ctx.moveTo(startX, startY); | |
ctx.lineTo(endX, endY); | |
ctx.stroke(); | |
ctx.closePath(); | |
} | |
var renderData = function renderData(type) { | |
var xInc = xMax / data.dataPoints.length;; | |
var prevX, prevY = 0; | |
for (var i = 0; i < data.dataPoints.length; i++) { | |
var pt = data.dataPoints[i]; | |
var ptY = (maxYValue - pt.y) * ratio; | |
if (ptY < margin.top) ptY = margin.top; | |
var ptX = (i * xInc) + margin.left; | |
if (i > 0 && type == renderType.lines) { | |
//Draw connecting lines | |
drawLine(ptX, ptY, prevX, prevY, 'black', 2); | |
} | |
if (type == renderType.points) { | |
var radgrad = ctx.createRadialGradient(ptX, ptY, 8, ptX - 5, ptY - 5, 0); | |
radgrad.addColorStop(0, 'Green'); | |
radgrad.addColorStop(0.9, 'White'); | |
ctx.beginPath(); | |
ctx.fillStyle = radgrad; | |
//Render circle | |
ctx.arc(ptX, ptY, 8, 0, 2 * Math.PI, false) | |
ctx.fill(); | |
ctx.lineWidth = 1; | |
ctx.strokeStyle = '#000'; | |
ctx.stroke(); | |
ctx.closePath(); | |
} | |
prevX = ptX; | |
prevY = ptY; | |
} | |
} | |
return { | |
renderType: renderType, | |
render: render | |
}; | |
}(); | |
var dataDef = { | |
title: "US Population Chart", | |
xLabel: 'Year', | |
yLabel: 'Population (millions)', | |
labelFont: '19pt Arial', | |
dataPointFont: '10pt Arial', | |
renderTypes: [CanvasChart.renderType.lines, CanvasChart.renderType.points], | |
dataPoints: [{ | |
x: '1790', | |
y: 3.9 | |
}, { | |
x: '1810', | |
y: 7.2 | |
}, { | |
x: '1830', | |
y: 12.8 | |
}, { | |
x: '1850', | |
y: 23.1 | |
}, { | |
x: '1870', | |
y: 36.5 | |
}, { | |
x: '1890', | |
y: 62.9 | |
}, { | |
x: '1910', | |
y: 92.2 | |
}, { | |
x: '1930', | |
y: 123.2 | |
}, { | |
x: '1950', | |
y: 151.3 | |
}, { | |
x: '1970', | |
y: 203.2 | |
}, { | |
x: '1990', | |
y: 248.7 | |
}, { | |
x: '2010', | |
y: 308.7 | |
}] | |
}; | |
CanvasChart.render('canvas', dataDef); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment