Last active
July 24, 2019 06:21
-
-
Save pjsier/205cbdeaed7be939beb0dcf37571f024 to your computer and use it in GitHub Desktop.
Horizontal Stacked Bar Chart
This file contains 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: mit |
This file contains 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> | |
<html> | |
<head> | |
<title>Diverging Stacked Bar Chart</title> | |
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> | |
<meta charset='utf-8' /> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<style> | |
body { | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
} | |
#chart { | |
max-width: 600px; | |
max-height: 400px; | |
} | |
</style> | |
</head> | |
<body> | |
<button onclick="removeOne()">Remove</button><button onclick="addOne()">Add</button> | |
<div id="chart"></div> | |
<script src="script.js"></script> | |
<script> | |
function getRandomInt(min, max) { | |
return Math.floor(Math.random() * (max - min + 1)) + min; | |
} | |
var chart = divergingBarChart(); | |
var data = []; | |
for (var i = 0; i < 3; ++i) { | |
data.push({ data: getRandomInt(1, 1000), label: "Test " + data.length }); | |
} | |
function resize() { | |
if (d3.select("#chart svg").empty()) { | |
return; | |
} | |
var w = +d3.select("#chart").style("width").replace(/(px)/g, ""); | |
chart.width(w); | |
chart.height(200); | |
d3.select("#chart").call(chart); | |
} | |
function removeOne() { | |
data.pop(); | |
d3.select("#chart").datum(data).call(chart); | |
} | |
function addOne() { | |
data.push({ data: getRandomInt(1, 1000), label: "Test " + data.length }); | |
d3.select("#chart").datum(data).call(chart); | |
} | |
document.addEventListener("DOMContentLoaded", function() { | |
d3.select("#chart").datum(data).call(chart); | |
d3.select(window).on('resize', resize); | |
}); | |
</script> | |
</body> | |
</html> |
This file contains 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
function divergingBarChart() { | |
var margin = {top: 20, right: 20, bottom: 20, left: 20}, | |
width = 600, | |
height = 150, | |
barHeight = 50, | |
padding = 10, | |
dataValue = function(d) { return +d.data; }, | |
labelValue = function(d) { return d.label; }, | |
color = ["#e24000", "#2c897f", "#434878"]; | |
function chart(selection) { | |
selection.each(function(data) { | |
data = data.map(function(d) { | |
return { value: dataValue(d), label: labelValue(d) }; | |
}); | |
var sumVals = d3.sum(data, function(d) { return d.value; }); | |
var barScale = d3.scaleLinear() | |
.domain([0, sumVals]) | |
.range([0, (width-margin.left-margin.right)]); | |
var svg = d3.select(this).selectAll("svg").data([data]); | |
var gEnter = svg.enter().append("svg").append("g"); | |
gEnter.append("g").attr("class", "rects") | |
.selectAll(".data-rects").data(data).enter() | |
.append("rect").attr("class", "data-rects"); | |
gEnter.selectAll("line.legend") | |
.data(data).enter() | |
.append("line").attr("class", "legend"); | |
gEnter.selectAll("text.legend") | |
.data(data).enter() | |
.append("text") | |
.attr("class", "legend") | |
.attr("font-size", 12); | |
var svg = selection.select("svg"); | |
svg.attr('width', width).attr('height', height); | |
var g = svg.select("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
var rectG = g.select("g.rects"); | |
var dataRects = rectG.selectAll(".data-rects").data(data, function(d) { return d.label; }); | |
dataRects.exit().remove(); | |
dataRects.enter().append("rect").attr("class", "data-rects"); | |
rectG.selectAll(".data-rects").transition() | |
.duration(750) | |
.attr("x", function(d, i) { | |
return data.slice(0, i).reduce(function (a, d) { return a + barScale(d.value); }, 1) + (padding / 2); | |
}) | |
.attr("y", height-margin.bottom-barHeight) | |
.attr("width", function(d) { return Math.max(barScale(d.value) - (padding / 2), 1); }) | |
.attr("height", barHeight) | |
.attr("fill", function(d, i) { return color[i]; }); | |
// Getting midpoint for legend | |
function legendX(d, i) { | |
return data.slice(0, i).reduce(function (a, d) { return a + barScale(d.value); }, (Math.max((barScale(d.value) - (padding / 2)), 1) / 2)) + (padding / 2); | |
}; | |
var legendLines = g.selectAll("line.legend").data(data, function(d) { return d.label; }); | |
legendLines.exit().remove(); | |
legendLines.enter().append("line").attr("class", "legend"); | |
g.selectAll("line.legend").transition() | |
.duration(750) | |
.attr("x1", legendX) | |
.attr("x2", legendX) | |
.attr("y1", height-margin.bottom-barHeight-15) | |
.attr("y2", height-margin.bottom-barHeight-45) | |
.attr("stroke", "#000000") | |
.attr("stroke-width", 0.5); | |
var legendText = g.selectAll("text.legend").data(data, function(d) { return d.label; }); | |
legendText.enter() | |
.append("text") | |
.attr("class", "legend") | |
.attr("font-size", 12); | |
legendText.exit().remove(); | |
g.selectAll("text.legend").transition() | |
.duration(750) | |
.attr("text-anchor", "middle") | |
.attr("x", legendX) | |
.attr("y", height-margin.bottom-barHeight-55) | |
.text(function(d) { return d3.format(",")(d.value); }); | |
}); | |
} | |
chart.margin = function(_) { | |
if (!arguments.length) return margin; | |
margin = _; | |
return chart; | |
}; | |
chart.width = function(_) { | |
if (!arguments.length) return width; | |
width = _; | |
return chart; | |
}; | |
chart.height = function(_) { | |
if (!arguments.length) return height; | |
height = _; | |
return chart; | |
}; | |
chart.dataValue = function(_) { | |
if (!arguments.length) return dataValue; | |
dataValue = _; | |
return chart; | |
}; | |
chart.labelValue = function(_) { | |
if (!arguments.length) return labelValue; | |
labelValue = _; | |
return chart; | |
}; | |
chart.color = function(_) { | |
if (!arguments.length) return color; | |
color = _; | |
return chart; | |
}; | |
return chart; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Patrick,
Can you give me a example of multiple rows of stacked column chart with dynamically adding stacks, while scrolling the new rows has to added, each row have multiple stacks ie)1000+ stacks and each stacks in the previous row are not matching to the current row ?
Thanks,
Gayathri