code everywhere

easy SVG donut charts

posted on March 1, 2015, 12:00 am in

the code

var donutChart = function(options) {
    
    var 
backgroundColor = options['backgroundColor'] || "#fff";
    var 
lineWidth = options['lineWidth'] || .40;
    var 
values = options['values'] || [0,1];
    var 
colors = options['colors'];
    var 
size = options['circleSize'];

    var 
svgns = "http://www.w3.org/2000/svg";
    var 
chart = document.createElementNS(svgns, "svg:svg");
    
chart.setAttribute("width", size);
    
chart.setAttribute("height", size);
    
chart.setAttribute("viewBox", "0 0 " + size + " " + size);

    
//calculate sum
    
var sum = 0;
    for( var 
x=0; x<values.length; x++) sum += values[x];
    
    
//calculate percentages
    
var slices = [];
    for( var 
x=0; x<values.length; x++) {
        
slices.push({
            
name     : 'x',
            
value     : values[x],
            
color     : colors[x],
            
perc     : values[x]/sum * 100,
            
draw     : -1
        
});
    }
    
    
//create array to draw
    
sum = 0;
    for( var 
x=slices.length-1; x>=0; x--) {
        for( var 
y=0; y<=x; y++)
            
sum += slices[y].perc;
       
slices[x].draw = sum;       
       
sum = 0;
    }

    
//fix 100+ problem
    
slices[slices.length-1].draw = 100;

    for( var 
x=slices.length-1; x>=0; x--) {
        var 
percentage = slices[x].draw;
        var 
color = slices[x].color;
                
        var 
path = document.createElementNS(svgns, "path");
        var 
unit = (Math.PI * 2) / 100;
        var 
startangle = 0;
        var 
endangle = percentage * unit - 0.001;
        var 
x1 = (size / 2) + (size / 2) * Math.sin(startangle);
        var 
y1 = (size / 2) - (size / 2) * Math.cos(startangle);
        var 
x2 = (size / 2) + (size / 2) * Math.sin(endangle);
        var 
y2 = (size / 2) - (size / 2) * Math.cos(endangle);
        var 
big = 0;
        if(
endangle - startangle > Math.PI) big = 1;

        var 
d = "M " + (size / 2) + "," + (size / 2) +  // Start at circle center
            
" L " + x1 + "," + y1 +                     // Draw line to (x1,y1)
            
" A " + (size / 2) + "," + (size / 2) +     // Draw an arc of radius r
            
" 0 " + big + " 1 " +                       // Arc details...
            
x2 + "," + y2 +                             // Arc goes to to (x2,y2)
            
" Z";                                       // Close path back to (cx,cy)

        
path.setAttribute("d", d); // Set this path 
        
path.setAttribute("fill", color);

        var 
title = document.createElementNS(svgns, "title");
        
title.appendChild(document.createTextNode(slices[x].name + " (" + (Math.floor(slices[x].perc * 100) / 100 ) + "%)"));
        
path.appendChild(title);

        
path.setAttribute("onmouseout", "evt.target.setAttribute('fill', '"+color+"');");
        
//path.setAttribute("onmouseover", "evt.target.setAttribute('fill', '#fafafa');");

        
chart.appendChild(path);
        
        var 
front = document.createElementNS(svgns, "circle");
        
front.setAttributeNS(null, "cx", (size / 2));
        
front.setAttributeNS(null, "cy", (size / 2));
        
front.setAttributeNS(null, "r",  (size * lineWidth));         // 0.0 to 0.5
        
front.setAttributeNS(null, "fill", backgroundColor);
        
chart.appendChild(front);        
    }
                
                
    
document.getElementById( options['divId'] ).appendChild(chart);
    return 
chart;
}

usage

var options = {
    
divId : "donutChart",
    
values : [25, 75, 150],
    
colors : [ 'red',  'blue', 'yellow'],
    
circleSize : 100,
    
backgroundColor : "#fff",
    
lineWidth : .35
};
donutChart(options);

var 
options = {
    
divId : "donutChart2",
    
values : [45,90],
    
colors : [ 'green', 'grey'],
    
circleSize : 100,
    
backgroundColor : "#fff",
    
lineWidth : .35
};
donutChart(options);

recent posts

< back
find something helpful? send us some coin BTC 19u6CWTxH4cH9V2yTfAemA7gmmh7rANgiv

(ad) Need Hosting? Try Linode, VPS Starting from $5

privacy policy