Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin: 0; position: fixed; top: 0; right: 0; bottom: 0; left: 0; }
svg { width: 100%; height: 100%; }
</style>
</head>
<body>
<svg></svg>
<script>
// options
var margin = {"top": 20, "right": 10, "bottom": 40, "left": 40 }
var width = 500;
var height = 500;
var rectWidth = 60;
var topPadding = 1.05;
// data
var data = [[0, 20, 40, 35, 60, 10],
[0, 50, 25, 30, 10, 20],
[0, 10, 20, 40, 10, 20],
[0, 35, 45, 10, 15, 25],
[0, 55, 30, 20, 15, 40]
];
// colors
var colors = ["black", "green", "blue", "teal", "purple", "navy"];
// ticks
var x_ticks = ["0 - 4", "4 - 8", "8 - 12", "12 - 16", "16 - 20"];
// calculate column totals
let colTotals = function(data) {
var cols = [];
for (var i = 0; i < data.length; i++){
var col = data[i].reduce(function(sum, value){
return (sum + value)}, 0);
cols.push(col);
}
return cols;
}
// calculate yMax
let dataMax = function(data) {
var colHeights = colTotals(data);
return d3.max(colHeights) * topPadding;
}
// scales
var xAxisScale = d3.scaleBand()
.domain(x_ticks)
.range([margin.left, width - margin.right]);
var xDataScale = d3.scaleBand()
.domain([0, 1, 2, 3, 4])
.range([margin.left, width - margin.right])
.paddingInner(0.2)
.paddingOuter(0.2)
var yMax = 1;
var yAxisScale = d3.scaleLinear()
.domain([0, yMax])
.range([height - margin.bottom, margin.top]);
// svg element
var svg = d3.select('svg');
// create bars array
let flatten = function(data, colors) {
var bars = [];
var barTotals = colTotals(data);
for (var i = 0; i < data.length; i++) {
var yStart = 0;
for (var j = 0; j < data[i].length; j++) {
if (j != 0) {
yStart += data[i][j-1];
}
var bar = {
"x" : i,
"y" : ((yStart+data[i][j]) / barTotals[i]),
"yStart": (yStart / barTotals[i]),
"height" : data[i][j],
"color" : colors[j],
"empty" : false,
};
bars.push(bar);
}
}
return {"bars": bars, "barTotals": barTotals};
}
// draw bars
var rectData = flatten(data, colors);
var bars = rectData.bars;
var barTotals = rectData.barTotals;
svg.selectAll('rect')
.data(bars)
.enter().append('rect')
.attr('x', function(d, i){
return xDataScale(bars[i].x)})
.attr('y', function(d, i){
return yAxisScale(bars[i].y)})
.attr('width', xDataScale.bandwidth)
.attr('height', function(d, i){
return yAxisScale(bars[i].yStart) - yAxisScale(bars[i].y)})
.attr('fill',function (d, i){
if (bars[i].empty){
return "white";
}else{
return bars[i].color;
}})
.attr('stroke', 'white')
// axes
var xAxis = d3.axisBottom()
.scale(xAxisScale)
var yAxis = d3.axisLeft()
.scale(yAxisScale)
.ticks(5)
.tickFormat(function(d){
return (d * 100) + '%'})
svg.append('g')
.attr('transform', 'translate(' + [0, height - margin.bottom] + ')')
.call(xAxis);
svg.append('g')
.attr('transform', 'translate(' + [margin.left, 0] + ')')
.call(yAxis);
</script>
</body>
https://d3js.org/d3.v4.min.js