drawing line charts with SVG
posted on April 25, 2015, 12:13 am in
An web page line chart based on SVG.
The Code
/*
* LineChart (April 25 2015)
* Copyright 2015, http://codeeverywhere.ca
* Licensed under the MIT license.
*/
(function() {
var lineChart = function(obj) {
var w = obj.width || document.getElementById('test').offsetWidth;
var h = obj.height || 250;
var background = obj.background || "#fff";
var showPoints = (obj.showPoints === undefined) ? false : obj.showPoints;
//if "auto", use offsetWidth
if (w == "auto") w = document.getElementById('test').offsetWidth;
//create svg elem
var svgns = "http://www.w3.org/2000/svg";
var chart = document.createElementNS(svgns, "svg:svg");
chart.setAttribute("width", w);
chart.setAttribute("height", h);
//calculate max, min values
var maxX = 0,
maxY = 0,
minX = obj.lines[0].data[0][0],
minY = obj.lines[0].data[0][1];
for (var y = 0; y < obj.lines.length; y++) {
var values = obj.lines[y].data;
for (var x = 0; x < values.length; x++) {
maxX = (values[x][0] > maxX) ? values[x][0] : maxX;
maxY = (values[x][1] > maxY) ? values[x][1] : maxY;
minX = (values[x][0] <= minX) ? values[x][0] : minX;
minY = (values[x][1] <= minY) ? values[x][1] : minY;
}
}
//for each line
for (var y = 0; y < obj.lines.length; y++) {
//get values
var values = obj.lines[y].data;
//if independent, find relative max, min values
if (obj.lines[y].independent) {
var maxX = 0,
maxY = 0,
minX = obj.lines[0].data[0][0],
minY = obj.lines[0].data[0][1];
for (var x = 0; x < values.length; x++) {
maxX = (values[x][0] > maxX) ? values[x][0] : maxX;
maxY = (values[x][1] > maxY) ? values[x][1] : maxY;
minX = (values[x][0] <= minX) ? values[x][0] : minX;
minY = (values[x][1] <= minY) ? values[x][1] : minY;
}
}
var circles = [];
//get start positions
var posX = 10 + ((values[0][0] - minX) / (maxX - minX)) * (w - 20);
var posY = 10 + (1 - (values[0][1] / maxY)) * (h - 20);
var linePrefix = "M " + posX + " " + posY;
var fillPrefix = "M " + posX + " " + (h - 10);
var coords = "";
//calculate points
for (var x = 0; x < values.length; x++) {
posX = 10 + ((values[x][0] - minX) / (maxX - minX)) * (w - 20);
posY = 10 + (1 - (values[x][1] / maxY)) * (h - 20);
coords += " L " + posX + " " + posY;
circles.push([posX, posY]);
}
//draw path
var path = document.createElementNS(svgns, "path");
path.setAttribute("d", linePrefix + coords);
path.setAttribute("stroke", obj.lines[y].color);
path.setAttribute("stroke-width", obj.lines[y].strokeWidth);
path.setAttribute("fill", "none");
chart.appendChild(path);
var fillTail = " L " + (posX) + " " + (h - 10);
var path = document.createElementNS(svgns, "path");
path.setAttribute("d", fillPrefix + coords + fillTail);
path.setAttribute("fill", obj.lines[y].fill);
chart.appendChild(path);
//draw points on line
if (showPoints) {
for (var x = 0; x < values.length; x++) {
var circle = document.createElementNS(svgns, "circle");
circle.setAttribute("cx", circles[x][0]);
circle.setAttribute("cy", circles[x][1]);
circle.setAttribute("r", "4");
circle.setAttribute("stroke-width", Math.floor(obj.lines[y].strokeWidth / 3));
circle.setAttribute("stroke", obj.lines[y].color);
circle.setAttribute("fill", background);
circle.setAttribute("onmouseout", "evt.target.setAttribute('r', '4');");
circle.setAttribute("onmouseover", "evt.target.setAttribute('r', '6');");
var title = document.createElementNS(svgns, "title");
var titleText;
if (obj.lines[y].title === undefined)
titleText = "(" + values[x][0] + ", " + values[x][1] + ")";
else
titleText = obj.lines[y].title(values[x][0], values[x][1]);
var text = document.createTextNode(titleText);
title.appendChild(text);
circle.appendChild(title);
chart.appendChild(circle);
}
}
//append to doc
var c = document.getElementById(obj.targetId);
c.style.width = w + "px";
c.style.height = h + "px";
c.appendChild(chart);
}
};
//add to window var
window.lineChart = lineChart;
})();
example usage
Add the script to your page, then call lineChart(obj), ex:
var obj = {
targetId : "test", // target <div>
width : "auto",
height : 350,
background : "#fff",
showPoints : true,
lines : [{
color : "#d22fff",
title : function(x, y){ return "x=" + x + ", y=" + y; },
independent: false, //draw line indepened of others
fill : "#e896ff",
strokeWidth : "6",
data : [ [3, 65], [4, 59], [5, 80] ]
},
{
color : "#baff39",
independent: false,
fill : "#ddff9e",
strokeWidth : "6",
data : [ [0, 35], [1, 43], [2, 33], [3, 13], [4, 22], [5, 35], [6, 20] ]
},
{
color : "#445546",
independent: false,
fill : "none",
strokeWidth : "6",
data : [ [1, 22], [2, 21], [3, 20], [4, 22], [5, 28], [6,2] ]
}]
};
lineChart(obj);
Online Demo
Try it out jsfiddle.net/h3j0sn05/