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);