Skip to content

Instantly share code, notes, and snippets.

@jaymollica
Last active October 23, 2019 21:34
Show Gist options
  • Save jaymollica/5a1e7c0e338d136af9fbefba5e53ef75 to your computer and use it in GitHub Desktop.
Save jaymollica/5a1e7c0e338d136af9fbefba5e53ef75 to your computer and use it in GitHub Desktop.
Stacked Pie Chart
license: gpl-3.0
height: 300

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.

<!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