chartDynamic = {
const svg = d3.create("svg").attr("viewBox", viewBox);
const selmodel = SelectionModel();
svg
.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x))
.append("text")
.attr("text-anchor", "end")
.attr("fill", "black")
.attr("font-size", "12px")
.attr("font-weight", "bold")
.attr("x", width)
.attr("y", -10)
.text("Fertility");
svg
.append("g")
.call(d3.axisLeft(y))
.append("text")
.attr("transform", "translate(20, 0) rotate(-90)")
.attr("text-anchor", "end")
.attr("fill", "black")
.attr("font-size", "12px")
.attr("font-weight", "bold")
.text("Life Expectancy");
const yearLabel = svg
.append("text")
.attr("class", "year")
.attr("x", 40)
.attr("y", height - 20)
.attr("fill", "#ccc")
.attr("font-family", "Helvetica Neue, Arial")
.attr("font-weight", 500)
.attr("font-size", 80)
.text(years[0]);
svg
.append("g")
.attr("transform", `translate(${width - 150}, 10)`)
.call((container) => legend(container, selmodel));
let countries = svg
.selectAll("circle.country")
.data(
dataDynamic.filter((d) => d.year === years[0]),
(d) => d.country
)
.join("circle")
.attr("class", "country")
.sort((a, b) => b.pop - a.pop)
.attr("opacity", 0.75)
.attr("fill", (d) => color(d.cluster))
.attr("cx", (d) => x(d.fertility))
.attr("cy", (d) => y(d.life_expect))
.attr("r", (d) => size(d.pop));
countries.append("title").text((d) => d.country);
countries
.on("mouseover", function () {
d3.select(this).attr("stroke", "#333").attr("stroke-width", 2);
})
.on("mouseout", function () {
d3.select(this).attr("stroke", null);
});
function changeYear(year) {
yearLabel.text(year);
countries = countries
.data(
dataDynamic.filter((d) => d.year === year),
(d) => d.country
)
// what we had before
// .join("circle")
.join(
// TODO(vishal): Add code to customize how countries enter the scene.
// Idea: fade in from transparent and grow from zero size
// Make sure new elements have their properties properly initialized!
(enter) =>
enter
.append("circle")
.attr("class", "country")
.attr("fill", (d) => color(d.cluster))
.attr("cx", (d) => x(d.fertility))
.attr("cy", (d) => y(d.life_expect))
.attr("r", (d) => 0),
(update) => update, // countries that still exist
// TODO(vishal): Add code to customize how countries exit the scene.
// Idea: fade out to transparent and shrink to zero size before removal
(exit) =>
exit
.transition()
.duration(1000)
.attr("r", 0)
.attr("opacity", 0)
.remove()
);
// TODO(vishal): Animate enter + update countries to current position and size
// Hint: If you modify opacity above, you probably want to update it here!
countries
.sort((a, b) => b.pop - a.pop)
.transition()
.duration(1000)
.attr("cx", (d) => x(d.fertility))
.attr("cy", (d) => y(d.life_expect))
.attr("r", (d) => size(d.pop))
.attr("opacity", 0.75);
countries
.on("mouseover", function () {
d3.select(this).attr("stroke", "#333").attr("stroke-width", 2);
})
.on("mouseout", function () {
d3.select(this).attr("stroke", null);
});
}
return Object.assign(svg.node(), { changeYear });
}