Use D3's general update pattern to animate bar chart transitions. Axis styling from this block.
This data takes the format:
name | value |
---|---|
String | Number |
license: gpl-3.0 |
Use D3's general update pattern to animate bar chart transitions. Axis styling from this block.
This data takes the format:
name | value |
---|---|
String | Number |
<!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
body { | |
margin: 0; | |
font-family: "Helvetica Neue", sans-serif; | |
} | |
.amount { | |
text-anchor: middle; | |
} | |
.x.axis .domain { | |
display: none; | |
} | |
</style> | |
</head> | |
<body> | |
<script src="https://d3js.org/d3.v6.min.js"></script> | |
<script> | |
const xVar = "name"; | |
const yVar = "value"; | |
const alpha = "abcdefg".split(""); | |
const margin = { left: 10, right: 10, top: 20, bottom: 20 }; | |
const width = innerWidth - margin.left - margin.right; | |
const height = innerHeight - margin.top - margin.bottom; | |
const svg = d3.select("body").append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom); | |
const g = svg.append("g") | |
.attr("transform", `translate(${[ margin.left, margin.top ]})`); | |
const x = d3.scaleBand() | |
.range([0, width]) | |
.domain(alpha) | |
.padding(.2); | |
const y = d3.scaleLinear() | |
.range([height, 0]) | |
.domain([0, 10]); | |
const xAxis = d3.axisBottom(x); | |
const yAxis = g => { | |
g.call( | |
d3.axisRight(y) | |
.tickFormat((d, i, e) => `${d}${i == e.length - 1 ? ` ${yVar}s` : ""}`) | |
.tickSize(width) | |
); | |
g.select(".domain").remove(); | |
g.selectAll(".tick:not(:first-of-type) line") | |
.attr("stroke", "#777") | |
.attr("stroke-dasharray", "2,2"); | |
g.selectAll(".tick text") | |
.attr("x", 4) | |
.attr("dy", -4); | |
} | |
g.append("g") | |
.attr("class", "x axis") | |
.attr("transform", `translate(0, ${height})`) | |
.call(xAxis); | |
g.append("g") | |
.attr("class", "y axis") | |
.call(yAxis); | |
const color = d3.scaleOrdinal(d3.schemeSet2); | |
redraw(randomData()); | |
d3.interval(() => { | |
redraw(randomData()); | |
}, 2000); | |
function redraw(data){ | |
// join | |
const bar = g.selectAll(".bar") | |
.data(data, d => d[xVar]); | |
const amount = g.selectAll(".amount") | |
.data(data, d => d[xVar]); | |
// update | |
bar | |
.transition() | |
.attr("y", d => y(d[yVar])) | |
.attr("height", d => height - y(d[yVar])); | |
amount | |
.transition() | |
.attr("y", d => y(d[yVar])) | |
.text(d => d[yVar]); | |
// enter | |
bar.enter().append("rect") | |
.attr("class", "bar") | |
.attr("x", d => x(d[xVar])) | |
.attr("y", d => y(d[yVar])) | |
.attr("width", x.bandwidth()) | |
.attr("height", d => height - y(d[yVar])) | |
.attr("fill", d => color(d[xVar])); | |
amount.enter().append("text") | |
.attr("class", "amount") | |
.attr("x", d => x(d[xVar]) + x.bandwidth() / 2) | |
.attr("y", d => y(d[yVar])) | |
.attr("dy", 16) | |
.attr("fill", d => d3.color(color(d[xVar])).darker(3)) | |
.text(d => d[yVar]); | |
} | |
function randomData(){ | |
return alpha.map(name => { | |
return { | |
name, | |
value: Math.round(d3.randomUniform(1, 10)()) | |
} | |
}); | |
} | |
</script> | |
</body> | |
</html> |