D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
MariamArabi
Full window
Github gist
Grouped to stacked bar chart (random function)
Built with
blockbuilder.org
<!DOCTYPE html> <meta charset="utf-8"> <style> form { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; position: absolute; left: 10px; top: 10px; } label { display: block; } </style> <form> <label><input type="radio" name="mode" value="grouped"> Grouped</label> <label><input type="radio" name="mode" value="stacked" checked> Stacked</label> </form> <svg width="960" height="500"></svg> <script src="https://d3js.org/d3.v4.min.js"></script> <script> var n = 5, // The number of series. m = 10; // The number of values per series. var xz = d3.range(m), yz = d3.range(n).map(function() { return bumps(m); }), y01z = d3.stack().keys(d3.range(n))(d3.transpose(yz)), yMax = d3.max(yz, function(y) { return d3.max(y); }), y1Max = d3.max(y01z, function(y) { return d3.max(y, function(d) { return d[1]; }); }); var svg = d3.select("svg"), margin = {top: 40, right: 10, bottom: 20, left: 10}, width = +svg.attr("width") - margin.left - margin.right, height = +svg.attr("height") - margin.top - margin.bottom, g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var x = d3.scaleBand() .domain(xz) .rangeRound([0, width]) .padding(0.08); var y = d3.scaleLinear() .domain([0, y1Max]) .range([height, 0]); var color = d3.scaleOrdinal() .domain(d3.range(n)) .range(d3.schemeCategory20b); var series = g.selectAll(".series") .data(y01z) .enter().append("g") .attr("fill", function(d, i) { return color(i); }); var rect = series.selectAll("rect") .data(function(d) { return d; }) .enter().append("rect") .attr("x", function(d, i) { return x(i); }) .attr("y", height) .attr("width", x.bandwidth()) .attr("height", 0); rect.transition() .delay(function(d, i) { return i * 10; }) .attr("y", function(d) { return y(d[1]); }) .attr("height", function(d) { return y(d[0]) - y(d[1]); }); g.append("g") .attr("class", "axis axis--x") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x) .tickSize(0) .tickPadding(6)); d3.selectAll("input") .on("change", changed); var timeout = d3.timeout(function() { d3.select("input[value=\"grouped\"]") .property("checked", true) .dispatch("change"); }, 2000); function changed() { timeout.stop(); if (this.value === "grouped") transitionGrouped(); else transitionStacked(); } function transitionGrouped() { y.domain([0, yMax]); rect.transition() .duration(500) .delay(function(d, i) { return i * 10; }) .attr("x", function(d, i) { return x(i) + x.bandwidth() / n * this.parentNode.__data__.key; }) .attr("width", x.bandwidth() / n) .transition() .attr("y", function(d) { return y(d[1] - d[0]); }) .attr("height", function(d) { return y(0) - y(d[1] - d[0]); }); } function transitionStacked() { y.domain([0, y1Max]); rect.transition() .duration(500) .delay(function(d, i) { return i * 10; }) .attr("y", function(d) { return y(d[1]); }) .attr("height", function(d) { return y(d[0]) - y(d[1]); }) .transition() .attr("x", function(d, i) { return x(i); }) .attr("width", x.bandwidth()); } // Returns an array of m psuedorandom, smoothly-varying non-negative numbers. // Inspired by Lee Byron’s test data generator. // https://leebyron.com/streamgraph/ function bumps(m) { var values = [], i, j, w, x, y, z; // Initialize with uniform random values in [0.1, 0.2). for (i = 0; i < m; ++i) { values[i] = 0.1 + 0.1 * Math.random(); } // Add five random bumps. for (j = 0; j < 5; ++j) { x = 1 / (0.1 + Math.random()); y = 2 * Math.random() - 0.5; z = 10 / (0.1 + Math.random()); for (i = 0; i < m; i++) { w = (i / m - y) * z; values[i] += x * Math.exp(-w * w); } } // Ensure all values are positive. for (i = 0; i < m; ++i) { values[i] = Math.max(0, values[i]); } return values; } </script>
https://d3js.org/d3.v4.min.js