code everywhere
technology, web services and applications

drawing line charts with SVG

posted on April 25, 2015, 12:13 am in js

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 
obj.width || document.getElementById('test').offsetWidth;
        var 
obj.height || 250;
        var 
background obj.background || "#fff";
        var 
showPoints = (obj.showPoints === undefined) ? false obj.showPoints;

        
//if "auto", use offsetWidth
        
if (== "auto"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 
0obj.lines.lengthy++) {
            var 
values obj.lines[y].data;
            for (var 
0values.lengthx++) {
                
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 0obj.lines.lengthy++) {
            
//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 
0values.lengthx++) {
                    
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)) * (20);
            var 
posY 10 + (- (values[0][1] / maxY)) * (20);

            var 
linePrefix "M " posX " " posY;
            var 
fillPrefix "M " posX " " + (10);

            var 
coords "";

            
//calculate points
            
for (var 0values.lengthx++) {
                
posX 10 + ((values[x][0] - minX) / (maxX minX)) * (20);
                
posY 10 + (- (values[x][1] / maxY)) * (20);
                
coords += " L " posX " " posY;
                
circles.push([posXposY]);
            }

            
//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) + " " + (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 
0values.lengthx++) {
                    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 document.getElementById(obj.targetId);
            
c.style.width "px";
            
c.style.height "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(xy){ return "x=" ", y=" y; },
        
independentfalse//draw line indepened of others
        
fill "#e896ff",
        
strokeWidth "6",
        
data : [ [365], [459], [580] ]
    },
    {
        
color "#baff39",
        
independentfalse,
        
fill "#ddff9e",
        
strokeWidth "6",
        
data : [ [035], [143], [233], [313], [422], [535], [620] ]
    },
    {
        
color "#445546",
        
independentfalse,
        
fill "none",
        
strokeWidth "6",
        
data : [ [122], [221], [320], [422], [528], [6,2] ]
    }]
};
lineChart(obj);

Online Demo

Try it out jsfiddle.net/h3j0sn05/

recent posts

< back