{
const width = 500;
const height = 100;
const padding = {top: 15, left: 0, right: 0, bottom: 0};
const graph = d3.select(DOM.svg(width, height));
graph.append("text")
.attr("y", padding.top)
.text("Action!")
.style("cursor", "hand")
.on("click", updateData);
let data = getIndexedRandomDataset();
const barPadding = 1;
const xScale = d3.scaleBand()
.domain(d3.range(data.length))
.rangeRound([padding.left, width - padding.right])
.paddingInner(0.05);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d[1])])
.range([padding.bottom, height - padding.top]);
const cScale = d3.scaleSequential()
.interpolator(d3.interpolateGreens)
.domain([0, d3.max(data, d => d[1])]);
graph.selectAll("rect")
.data(data, d => d[0])
.enter()
.append("rect")
.attr("x", (d, i) => xScale(i))
.attr("y", d => height - yScale(d[1]))
.attr("width", xScale.bandwidth())
.attr("height", d => yScale(d[1]))
.attr("fill", d => cScale(d[1]));
graph.selectAll("text.label")
.data(data)
.enter()
.append("text")
.attr("class", "label")
.text(d => d[1])
.attr("x", (d, i) => xScale(i) + xScale.bandwidth() / 2)
.attr("y", d => height - yScale(d[1]) + 15)
.attr("text-anchor", "middle")
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "white");
function updateData() {
data.push(...getIndexedRandomDataset(data[data.length - 1][0], 1, 40));
data.shift();
// update the scales
yScale.domain([0, d3.max(data, d => d[1])]);
cScale.domain([0, d3.max(data, d => d[1])]);
let bars = graph.selectAll("rect")
.data(data, d => d[0]);
bars.enter()
.append("rect")
.attr("x", (d, i) => xScale(i))
.attr("y", d => height - yScale(0))
.attr("width", xScale.bandwidth())
.attr("height", d => yScale(0))
.attr("fill", d => cScale(d[1]))
.merge(bars)
.transition()
.attr("x", (d, i) => xScale(i))
.attr("y", d => height - yScale(d[1]))
.attr("height", d => yScale(d[1]))
.attr("fill", d => cScale(d[1]));
bars.exit()
.transition()
.attr("y", d => height - yScale(0))
.attr("height", d => yScale(0))
.remove();
let labels = graph.selectAll("text.label")
.data(data, d => d[0]);
labels.enter()
.append("text")
.attr("class", "label")
.text(d => d[1])
.attr("x", (d, i) => xScale(i) + xScale.bandwidth() / 2)
.attr("y", d => height - yScale(0) + 15)
.attr("text-anchor", "middle")
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "white")
.merge(labels)
.transition()
.text(d => d[1])
.attr("y", d => height - yScale(d[1]) + 15)
.attr("x", (d, i) => xScale(i) + xScale.bandwidth() / 2);
// here we specify what to do with removed data: move to the left with a transition and remove
labels.exit()
.transition()
.attr("y", d => height - yScale(0) + 15)
.remove();
}
return graph.node();
}