See also: Bar Update Pattern.
TODO: Figure out how to apply the margin convention on Canvas.
forked from HarryStevens's block: Bar Update Pattern on Canvas
license: gpl-3.0 |
See also: Bar Update Pattern.
TODO: Figure out how to apply the margin convention on Canvas.
forked from HarryStevens's block: Bar Update Pattern on Canvas
<!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
body { | |
margin: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://unpkg.com/[email protected]/lib/jeezy.min.js"></script> | |
<script> | |
var alpha = "abcdefg".split(""); | |
var min = 0, max = 10; | |
var width = window.innerWidth, height = window.innerHeight; | |
var canvas = d3.select("body").append("canvas") | |
.attr("width", width) | |
.attr("height", height); | |
var context = canvas.node().getContext("2d"); | |
var customBase = document.createElement("custom"); | |
var custom = d3.select(customBase); | |
var x = d3.scaleBand() | |
.rangeRound([0, width]) | |
.domain(alpha) | |
.padding(.2); | |
var y = d3.scaleLinear() | |
.range([height, 0]) | |
.domain([min, max]); | |
var color = d3.scaleOrdinal(["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494"]); | |
bind(random_data()); | |
draw(); | |
d3.interval(function(){ | |
bind(random_data()); | |
var t = d3.timer(function(elapsed) { | |
draw(); | |
if (elapsed > 750) t.stop(); | |
}); | |
}, 1000); | |
function bind(data){ | |
var x_var = Object.keys(data[0])[0], y_var = Object.keys(data[0])[1]; | |
// join | |
var bar = custom.selectAll("custom.bar") | |
.data(data, function(d){ return d[x_var]; }); | |
var amount = custom.selectAll("custom.amount") | |
.data(data, function(d){ return d[x_var]; }); | |
// update | |
bar | |
.transition() | |
.attr("y", function(d){ return y(d[y_var]); }) | |
.attr("height", function(d){ return height - y(d[y_var]); }); | |
amount | |
.transition() | |
.attr("y", function(d){ return y(d[y_var]); }) | |
.text(function(d){ return d[y_var]; }); | |
// enter | |
bar.enter().append("custom") | |
.attr("class", "bar") | |
.attr("x", function(d){ return x(d[x_var]); }) | |
.attr("y", function(d){ return y(d[y_var]); }) | |
.attr("width", x.bandwidth()) | |
.attr("height", function(d){ return height - y(d[y_var]); }) | |
.attr("fill", function(d){ return color(d[x_var]); }); | |
amount.enter().append("custom") | |
.attr("class", "amount") | |
.attr("x", function(d){ return x(d[x_var]) + x.bandwidth() / 2; }) | |
.attr("y", function(d){ return y(d[y_var]); }) | |
.attr("dy", 16) | |
.text(function(d){ return d[y_var]; }); | |
} | |
function draw(){ | |
context.fillStyle = "#fff"; | |
context.fillRect(0, 0, width, height); | |
var bars = custom.selectAll("custom.bar"); | |
bars.each(function(d, i){ | |
var node = d3.select(this); | |
context.fillStyle = node.attr("fill"); | |
context.fillRect(node.attr("x"), node.attr("y"), node.attr("width"), node.attr("height")) | |
}); | |
var amounts = custom.selectAll("custom.amount"); | |
amounts.each(function(d, i){ | |
var node = d3.select(this); | |
context.font = "16px Helvetica Neue"; | |
context.fillStyle = "#fff"; | |
var x = +node.attr("x"); | |
var y = +node.attr("y"); | |
var dy = +node.attr("dy"); | |
context.fillText(node.text(), x, y + dy); | |
}); | |
} | |
function random_data(){ | |
return alpha.map(function(d, i){ | |
return { | |
name: d, | |
value: jz.num.randBetween(min + 1, max) | |
} | |
}); | |
} | |
</script> | |
</body> | |
</html> |