Skip to content

← Examples

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],
  })
);