Bubble Treemap
Seventy countries as circles sized by population, packed by region and continent, with a contour of circular arcs around each region and a wider one around each continent.
ts
import { Shape, chart, circle, enclose, pack } from "gofish-graphics";
import { countryPopulations } from "./dataset";
const country = (d: CountryPopulation[]) =>
circle({ r: 1.6 * Math.sqrt(d[0].pop), fill: "continent" })(d);
const container = document.getElementById("app");
chart(countryPopulations)
.flow(
pack({ by: "continent", spacing: 4 }),
enclose({
shape: Shape.fillet({ radius: 12 }),
padding: 4,
fill: "none",
stroke: "#333",
strokeWidth: 1.5,
}),
pack({ by: "region", spacing: 4 }),
enclose({
shape: Shape.fillet({ radius: 8 }),
padding: 4,
fill: "none",
stroke: "#999",
}),
pack()
)
.mark(country)
.render(container, { w: 720, h: 600 });dataset.ts
ts
/**
* Seventy countries grouped by continent, then by region, with a rough
* 2023 population in millions. Used by the bubble treemap stories (#1221).
*
* The `uncertainty` column is MADE UP for illustration: a per-region spread,
* in percent, standing in for the standard deviation the bubble treemap paper
* (Görtler et al., TVCG 2018) draws as contour distance. It is not a real
* measure of anything.
*/
export type CountryPopulation = {
continent: string;
region: string;
country: string;
pop: number;
uncertainty: number;
};
const rows: [string, string, string, number][] = [
// Asia
["Asia", "East Asia", "China", 1410],
["Asia", "East Asia", "Japan", 124],
["Asia", "East Asia", "South Korea", 52],
["Asia", "East Asia", "Taiwan", 24],
["Asia", "East Asia", "North Korea", 26],
// … 65 more rows
];
// A made-up spread per region, in percent of population (see above).
const regionUncertainty: Record<string, number> = {
"East Asia": 1,
"South Asia": 4,
"Southeast Asia": 3,
"Western Asia": 6,
"West Africa": 10,
"East Africa": 8,
"North Africa": 5,
"Central & South": 12,
"Western Europe": 1,
"Southern Europe": 1.5,
"Eastern Europe": 3,
"North America": 1.5,
"South America": 4,
};
export const countryPopulations: CountryPopulation[] = rows.map(
([continent, region, country, pop]) => ({
continent,
region,
country,
pop,
uncertainty: regionUncertainty[region],
})
);