updateBarsAndLabels = (svg, data) => {
const t = svg.transition().duration(750);
xScale.domain(d3.range(data.length));
yScale.domain([0, d3.max(data, d => d.value)]);
const barUpdate = svg
.selectAll("rect")
.data(data, key)
.attr("fill", "darkblue")
.call(update =>
update
.transition(t)
.attr("x", (d, i) => xScale(i))
.attr("y", d => height - yScale(d.value))
.attr("width", xScale.bandwidth())
.attr("height", d => yScale(d.value))
);
const barEnter = barUpdate
.enter()
.append("rect")
.attr("x", width)
.attr("y", d => height - yScale(d.value))
.attr("width", xScale.bandwidth())
.attr("height", d => yScale(d.value))
.attr("fill", "steelblue")
.call(update =>
update
.transition(t)
.attr("x", (d, i) => xScale(i))
.attr("y", d => height - yScale(d.value))
.attr("width", xScale.bandwidth())
.attr("height", d => yScale(d.value))
);
const barExit = barUpdate
.exit()
.attr("fill", "red")
.call(exit =>
exit
.transition(t)
.attr("x", -xScale.bandwidth())
.remove()
);
const textUpdate = svg
.selectAll("text")
.data(data, key)
.call(update =>
update
.transition(t)
.attr("x", (d, i) => xScale(i) + xScale.bandwidth() / 2)
.attr("y", d => height - yScale(d.value) + 20)
);
const textEnter = textUpdate
.enter()
.append("text")
.attr("x", width)
.attr("y", d => height - yScale(d.value) + 20)
.attr("font-family", "sans-serif")
.attr("font-size", "14px")
.attr("fill", "white")
.attr("text-anchor", "middle")
.text(d => d.value)
.call(enter =>
enter
.transition(t)
.attr("x", (d, i) => xScale(i) + xScale.bandwidth() / 2)
);
const textExit = textUpdate
.exit()
.attr("fill", "black")
.call(exit =>
exit
.transition(t)
.attr("x", -xScale.bandwidth())
.remove()
);
}