{
const width = 600;
const height = 600;
const svg = d3.create("svg").attr("width", width).attr("height", height);
const data = populations.filter((d) => d.value > 10000000);
const color = d3
.scaleOrdinal()
.domain(["Asia", "Europe", "Africa", "Oceania", "Americas"])
.range(d3.schemeSet1);
const size = d3.scaleLinear().domain([0, 1400000000]).range([7, 100]);
const nodes = svg
.append("g")
.selectAll("circle")
.data(data)
.join("circle")
.attr("r", (d) => size(d.value))
.attr("cx", width / 2)
.attr("cy", height / 2)
.attr("stroke", "black")
.style("stroke-width", 1)
.style("fill", (d) => color(d.region))
.style("fill-opacity", 0.8);
nodes.on("click", (event, d) => {
console.log("You clicked on", d);
});
// Part 1: Add a thicker border to nodes as the mouse is on top of them.
// You'll need to modify the "mouseover" and "mouseout" callback functions.
nodes
.on("mouseover", (event) => {
d3.select(event.target).style("stroke-width", 5);
})
.on("mouseout", (event) => {
d3.select(event.target).style("stroke-width", 1);
});
// Part 2: Add a tooltip to the circles.
// To start this part of the exercise, uncomment the code block below.
// You should see a tooltip on your circles that says "I'm a circle"
//
// Note: calling nodes.on("mouseover", ...) overwrites your function above.
// If you want to keep the hovering behavior, you'll have to put it inside the functions below.
//
// Make the tooltip say the name of the country that the mouse is on top of.
// You can add other details, like the region, subregion or population.
const tooltip = d3
.select("body")
.append("div")
.style("position", "absolute")
.style("visibility", "hidden")
// .text("I'm a circle!");
nodes
.on("mouseover", (event, d) => {
// When the mouse enters a circle, draw the tooltip.
tooltip.style("visibility", "visible");
d3.select(event.target).style("stroke-width", 5);
tooltip.html(`<p> ${d.key}, ${d.subregion}, ${d.region} </p>`)
})
.on("mousemove", (event, d) => {
// Keep the tooltip aligned with the mouse as we move it.
tooltip
.style("top", event.clientY - 10 + "px")
.style("left", event.clientX + 10 + "px");
})
.on("mouseout", (event, d) => {
// As the mouse leaves, we want to remove the tooltip
tooltip.style("visibility", "hidden");
d3.select(event.target).style("stroke-width", 1);
});
const simulation = d3
.forceSimulation()
.force(
"center",
d3
.forceCenter()
.x(width / 2)
.y(height / 2)
) // Attraction to the center of the svg area
.force("charge", d3.forceManyBody().strength(0.1)) // Nodes are attracted one each other of value is > 0
.force(
"collide",
d3
.forceCollide()
.strength(0.2)
.radius(function (d) {
return size(d.value) + 3;
})
.iterations(1) // Force that avoids circle overlapping
)
.nodes(data)
.on("tick", () => {
nodes.attr("cx", (d) => d.x).attr("cy", (d) => d.y);
});
return svg.node();
}