The stacked pie chart is meant to look like a stacked bar chart, but within the setting of a pie chart. This form allows for a better scrolling experience than with pie charts, and provide an easy method of comparison when placed in a series. Works best with small varieties of information.
Last active
October 23, 2019 21:34
-
-
Save jaymollica/5a1e7c0e338d136af9fbefba5e53ef75 to your computer and use it in GitHub Desktop.
Stacked Pie Chart
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
license: gpl-3.0 | |
height: 300 |
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
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<style> | |
#piebar-chart { | |
width:960px; | |
margin-left:3%; | |
} | |
svg { | |
font-family: arial; | |
font-size:12px; | |
} | |
.horizontal-chart-title { | |
font-size:14px; | |
fill:gray; | |
} | |
</style> | |
<body> | |
<div id="piebar-chart"></div> | |
</body> | |
<script> | |
function stackedHorizontalBarChart(pieData, divName, title) { | |
// Draw for the first time to initialize. | |
resized(); | |
window.addEventListener("resize", resized); | |
function resized() { | |
//remove previously rendered svg | |
d3.select(divName + " svg").remove(); | |
chartData = calculateChartData(pieData, divName); | |
var widths = chartData.widths; | |
var keys = chartData.keys; | |
var lineLabels = chartData.labels; | |
var p = 0; | |
var colors = ["#1DACE8", "#1C366B", "#F24D29", "#E5C4A1", "#C4CFD0", "#d0743c", "#ff8c00"]; | |
var svg = d3.select(divName) | |
.append('svg') | |
.attr('width', $(divName).width()) | |
.attr('height', 300); | |
var g = svg.append("g") | |
.attr("transform", "translate(" + 0 + "," + -16 + ")") | |
.attr("class", "labels"); | |
svg.append("text") | |
.attr("x", $(divName).width() - 180 ) | |
.attr("y", 170) | |
.style("text-anchor", "start") | |
.text(title) | |
.attr("class", "horizontal-chart-title"); | |
svg.append("g") | |
.attr("class", "lines"); | |
svg.selectAll('rect') | |
.data(widths) | |
.enter() | |
.append('rect') | |
.attr('width', function(d){return d;}) | |
.attr('x',function(d, i){return sum(widths, 0, i); }) | |
.attr('fill', function(d, i){ return colors[i]; }) | |
.attr('y',120) | |
.attr('height', 100); | |
var labels = g.selectAll(".labels") | |
.data(chartData.keys) | |
.enter(); | |
labels.append("text") | |
.attr("text-anchor",function(index,value) {return "start";}) | |
.text( function(d, i) { return lineLabels[i]; }) | |
.attr("class", function(d,i) { | |
className = d.toLowerCase(); | |
className =className.split(' ').join('-'); | |
return "text-"+className+"-label"; | |
}) | |
.attr("transform", function(d, i) { | |
coefficient = 0; | |
h = 120; | |
allWidth = 0 | |
if (i > 0) { | |
$.each(widths, function(index, value) { | |
allWidth += value; | |
if(i>index) { | |
coefficient += value / 1; | |
} | |
}); | |
} | |
totalWidth = coefficient + this.getBBox().width; | |
elWidth = $(divName).width() - 200; | |
if (totalWidth > elWidth) { | |
// diff = totalWidth - elWidth; | |
// coefficient = allWidth - (this.getBBox().width + widths[i]/2); | |
// p = p + 1; | |
h = h - (12 * p); | |
p = p - 1; | |
} | |
return "translate("+ coefficient + "," + h + ")"; | |
}); | |
labels.append("line") | |
.attr("x1", function(d, i){ return sum(chartData.widths, 0, i) }) | |
.attr("x2", function(d, i){ return sum(chartData.widths, 0, i) }) | |
.attr("y1", function(d, i){ | |
return 125; | |
}) | |
.attr("y2", 180) | |
.attr("stroke-width", 1) | |
.attr("stroke", "gray") | |
.attr("stroke-dasharray", "1,1"); | |
} | |
} | |
function calculateChartData(data, divName) { | |
var elWidth = $(divName).width() - 200; | |
var keys = new Array(); | |
var values = new Array(); | |
var widths = new Array(); | |
var labels = new Array(); | |
var totalValues = 0; | |
$.each( data.items, function( key, value ) { | |
keys.push(value.description); | |
values.push(value.count); | |
totalValues += value.count; | |
}); | |
var percent = 0; | |
$.each(values, function(index, value) { | |
percent = (value / totalValues); | |
labels.push(keys[index] + ' ' + Math.round(percent * 100)+"%"); | |
width = percent * elWidth; | |
width = Math.round(width); | |
widths.push(width); | |
}); | |
var chartData = {'widths': widths, 'keys': keys, 'values': values, 'labels': labels} | |
return chartData; | |
} | |
function sum(array, start, end) { | |
var total = 0; | |
for(var i=start; i<end; i++) total += array[i]; | |
return total; | |
} | |
var data = { | |
"items": [{ | |
"description": "Photography", | |
"count": 19289 | |
}, { | |
"description": "Painting and Sculpture", | |
"count": 8880 | |
}, { | |
"description": "Architecture and Design", | |
"count": 6513 | |
}, { | |
"description": "Media Arts", | |
"count": 227 | |
}] | |
}; | |
stackedHorizontalBarChart(data, "#piebar-chart", "SFMOMA Collection"); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment