Public
Edited
Nov 12, 2024
Fork of Scatter plot
1 fork
Insert cell
Insert cell
{
const svg = d3.create("svg").attr("width", width).attr("height", height);

// Axis
svg
.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(xAxis);

svg.append("g").attr("transform", `translate(${margin.left}, 0)`).call(yAxis);


// Bubbles
const bubbles = svg
.selectAll("bubbles")
.data(data)
.enter()
.append("circle")
.attr("class", "country_bubbles")
.attr("cx", (d) => xScale(d["Income per person"]))
.attr("cy", (d) => yScale(d["Life expectancy "]))
// .attr("r", 4.2)
//.attr("r", (d) => radiusScale(d.Population))
.attr("r", 0)
.attr("fill", (d) => findColors(d.region))
.style("fill-opacity", 0.74)
.attr("stroke", "#555")
.on("mousemove", function (event, d, index) {

toolTip
.style("display", "block")
.html(
`<p>
<span style="font-weight:bold;">Region: </span>
<span style=" color:${findColors(d.region)}"> ${d.region}</span>
<br>
<span style="font-weight:bold">Country: </span>
${d.name}
<br>
<span style="font-weight:bold">Population: </span>
${d3.format(".2s")(d.Population)}</span>
</p>`
);
let yoffset = 52;
let xoffset = 10;
toolTip
.style("left", event.pageX - d3.select(".toolTip").node().offsetWidth - xoffset + "px")
.style("top", event.pageY - yoffset + "px");

d3.select(this)
.style("stroke-width", 3)
//.style("fill", "#fff")
.style("fill-opacity", 0.95);
})
.on("mouseout", function () {
toolTip
.style("display", "none");
d3.select(this)
.style("stroke-width", 1)
.style("fill", (d) => findColors(d.region))
.style("fill-opacity", 0.74);
});
bubbles
.transition()
.duration(1500)
.attr("r", function(d)
{
console.log(d)
return radiusScale(d.Population);
});
// Tooltip
const toolTip = d3.select("body").append("div").attr("class", "toolTip");

getLegend(svg, "vertical", 16, 7, 5, domains.length)

return svg.node();
}
Insert cell
Insert cell
findColors = (region) => {
let color;
if (region === "asia") {
color = "#E74F2A";
} else if (region === "europe") {
color = "#FFE473";
} else if (region === "africa") {
color = "#234FBF";
} else if (region === "americas") {
color = "#00835D";
}
return color;
}
Insert cell
Insert cell
yAxis = d3.axisLeft(yScale) //.ticks(5)
Insert cell
Insert cell
xAxis = d3
.axisBottom(xScale)
.tickFormat(d3.format("~s"))
.tickValues([500, 1000, 2000, 4000, 8000, 16000, 32000, 64000])
Insert cell
Insert cell
yScale = d3
.scaleLinear()
.domain(d3.extent(data, (d) => d["Life expectancy "]))
.range([height - margin.bottom, margin.top])
Insert cell
xScale = d3
.scaleLog()
// .domain(d3.extent(data, (d) => d["Income per person"]))
.domain([500, d3.max(data, (d) => d["Income per person"])])
// .domain([0, d3.max(data, (d) => d["Income per person"])])
.range([margin.left, width - margin.right])
Insert cell
radiusScale = d3
.scaleSqrt()
.domain([0, d3.max(data, (d) => d.Population)])
.range([0, 50])
Insert cell
margin = ({ top: 20, right: 100, bottom: 60, left: 60 })
Insert cell
height = 540
Insert cell
Insert cell
Insert cell
[...new Set(data.map((d) => d.region))]
Insert cell
Insert cell
data = life_expectancy
.map((d) => {
d["Income per person"] = gdp_per_capita.find((g) => g.name === d.name)[
"Income per person"
];
d.Population = population.find((p) => p.name === d.name).Population;
d.region = region.find((r) => r.name === d.name).four_regions;
return d;
})
.sort((a, b) => b.Population - a.Population)
Insert cell
life_expectancy = d3
.csvParse(
await FileAttachment("gapminder_lifeExpectancy.csv").text(),
d3.autoType
)
.filter((d) => d.time === 2022)
Insert cell
gdp_per_capita = d3
.csvParse(
await FileAttachment("gapminder_gdpPerCapita.csv").text(),
d3.autoType
)
.filter((d) => d.time === 2022)
Insert cell
population = d3
.csvParse(
await FileAttachment("gapminder_population.csv").text(),
d3.autoType
)
.filter((d) => d.time === 2022)
Insert cell
region = d3.csvParse(
await FileAttachment("gapminder_region.csv").text(),
d3.autoType
)
Insert cell
// Vertical and horizontal Legend
function getLegend(svg, direction, key_size, item_padding, text_x_offset, classes){
const legend_height = classes * (key_size + item_padding);

// Legend as a group
const legend = svg.append("g")
// Apply a translation to the entire group
.attr("transform", `translate(${width/1.09}, ${legend_height})`)
// Boxes
legend
.selectAll("boxes")
.data(domains)
.enter()
.append("rect")
.attr("x", 0)
.attr("y", (d, i) => (i * (key_size + item_padding)))
.attr("width", key_size)
.attr("height", key_size)
.style("fill", (d) => findColors(d));
// Labels
legend
.selectAll("labels")
.data(domains)
.enter()
.append("text")
.attr("x", key_size)
.attr("y", (d, i) => i * (key_size + item_padding))
.attr("dx", text_x_offset)
.attr("dy", ".5em")
.text((d) => d)
.attr("text-anchor", "left")
.style("alignment-baseline", "middle")
.style("font-family", "sans-serif")
.style("text-transform", "capitalize")
.style("font-size", key_size+"px");

}

Insert cell
domains = ["asia", "americas","africa","europe"];
Insert cell
Insert cell
html`<style>

.toolTip {
position: absolute;
background-color: #A3E2B5;
padding: 0px 10px;
font-size: 21px;
border: .85px solid #333;
border-radius: 4px;
font-family: arial;
font-weight: 500;
line-height: 1.2;
letter-spacing: -.5px;
text-transform:capitalize;
}

.label {
text-transform:capitalize
font-color:red;
}
</style>`
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more