Created
October 22, 2018 14:40
-
-
Save HTLife/f4f280c3257267d38c540e2648339b31 to your computer and use it in GitHub Desktop.
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> | |
<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 = 4, // The number of series. | |
m = 58; // The number of values per series. | |
// The xz array has m elements, representing the x-values shared by all series. | |
// The yz array has n elements, representing the y-values of each of the n series. | |
// Each yz[i] is an array of m non-negative numbers representing a y-value for xz[i]. | |
// The y01z array has the same structure as yz, but with stacked [y₀, y₁] instead of y. | |
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.schemeCategory20c); | |
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. | |
// http://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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment