chart = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, 975, 900])
.attr("text-anchor", "middle")
.attr("font-family", "sans-serif")
.attr("font-size", 10);
const legend = svg
.append("g")
.attr("fill", "#777")
.attr("transform", "translate(905,600)")
.selectAll("g")
.data([1e6, 5e6, 15e6])
.join("g");
legend
.append("circle")
.attr("fill", "none")
.attr("stroke", "#bbb")
.attr("cy", d => -radius(d))
.attr("r", radius);
legend
.append("text")
.attr("y", d => -2 * radius(d))
.attr("dy", "1.3em")
.text(d3.format("~s"));
let bubble = svg.append("g").selectAll("g");
return Object.assign(svg.node(), {
update(year) {
const t = svg
.transition()
.duration(delay)
.ease(d3.easeLinear);
bubble = bubble
.data(data.filter(d => d.year === year), d => d.id)
.join(
enter =>
enter
.append("g")
.attr("transform", d => `translate(0, 700) scale(.00001)`)
.call(g =>
g
.append("path")
.attr("class", "state")
.attr("fill", d => `hsl(${hues.get(d.id)}, 50%, 50%)`)
.attr("opacity", 0)
.attr("stroke", "white")
.attr("stroke-linejoin", "round")
.attr("d", d => path(d.feature))
.attr(
"transform",
d => `
scale(${40/Math.sqrt(path.area(d.feature))})
translate(${path.centroid(d.feature).map(d => -d)})`
)
.transition(t)
.attr("opacity", 0.5)
)
.call(g =>
g
.append("text")
.attr("dy", "0.35em")
.attr("fill-opacity", 0)
.attr("y", -2)
.call(text =>
text
.append("tspan")
.style("font-variant-numeric", "tabular-nums")
.attr("x", 0)
.attr("y", 0)
.text(0)
)
.transition(t)
.attr("fill-opacity", 1)
)
,
update => update,
exit =>
exit.call(bubble =>
bubble
.transition(t)
.call(g => g.select("circle").attr("r", 0))
.call(g => g.select("text").attr("fill-opacity", 0))
.call(g => g.select("tspan").call(textTween, 0))
.remove()
)
);
const sorted = data
.filter(d => d.year === year)
.sort((a, b) => b.value - a.value)
.map(d => d.id);
x.domain(d3.extent(data.filter(d => d.year === year), d => d.value));
bubble
.transition(t)
.each(d => {
// console.log(d, x(d.value));
})
.attr(
"transform",
d => ` translate(${x(d.value)}, ${y(sorted.indexOf(d.id))}) scale(${Math.sqrt(d.value)/2500})`,
);
bubble
.select("tspan")
.transition(t)
.call(textTween, d => d.value);
}
});
}