Built with blockbuilder.org
forked from ywwhack's block: stack transition
license: mit |
Built with blockbuilder.org
forked from ywwhack's block: stack transition
<!DOCTYPE html> | |
<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; } | |
</style> | |
</head> | |
<body> | |
<script> | |
var svg = d3.select("body").append("svg") | |
.attr("width", 960) | |
.attr("height", 500) | |
var data = [ | |
{ year: 2005, bananas: [10, 20, 30, 40], apples: [20, 10, 30, 50], pears: [30, 10, 20, 50] }, | |
{ year: 2006, bananas: [30, 40, 20, 10], apples: [20, 10, 10, 50], pears: [30, 20, 20, 50] }, | |
{ year: 2007, bananas: [10, 30, 30, 40], apples: [20, 10, 30, 50], pears: [40, 10, 20, 50] } | |
] | |
const BAR_HEIGHT = 50 | |
const FRUITS = ['bananas', 'apples', 'pears'] | |
const COLORS = ['#21CD69', '#f8bc29', '#fb4848', '#ccc'] | |
svg.selectAll('g.stack') | |
.data(FRUITS) | |
.enter().append('g') | |
.attr('class', 'stack') | |
.attr('transform', (d, i) => `translate(0, ${i * (BAR_HEIGHT + 10)})`) | |
function update (year) { | |
var filteredData = data.filter(i => i.year === year)[0] | |
svg.selectAll('g.stack').nodes() | |
.forEach((node, i) => { | |
const fruitName = FRUITS[i] | |
const t = d3.transition().duration(1000) | |
const stack = d3.select(node) | |
.selectAll('rect') | |
.data(filteredData[fruitName], d => d) | |
stack.exit() | |
.transition(t) | |
.attr('width', 0) | |
.remove() | |
let x = 0 | |
stack.enter().append('rect') | |
.attr('y', 0) | |
.attr('height', BAR_HEIGHT) | |
.merge(stack) | |
.attr('fill', (d, i) => COLORS[i]) | |
.transition(t) | |
.attr('x', (d, i) => { | |
const retX = x | |
x += d * 5 | |
return retX | |
}) | |
.attr('width', d => d * 5) | |
}) | |
} | |
let year = 2005 | |
let inc = 0 | |
update(year) | |
setInterval(() => { | |
inc = (inc + 1) % 3 | |
update(year + inc) | |
}, 2000) | |
</script> | |
</body> |