Public
Edited
Sep 23, 2021
Insert cell
Insert cell
Insert cell
Insert cell
{
for (let i = 0; i < 200; i++){
simulation.tick();
}

const fills = world.features.map((ft, i) => {
const value = getValue(ft.properties.ISO_A3);
return {
index: i,
ISO3: ft.properties.ISO_A3,
POP_EST: ft.properties.POP_EST,
x: ft.x,
y: ft.y,
radius: r(ft.properties.POP_EST),
startAngle: 0,
endAngle: value/10 * tau,
padAngle: 0,
value: value/10
}

});

const bases = world.features.map((ft, i) => {
return {
index: i,
ISO3: ft.properties.ISO_A3,
POP_EST: ft.properties.POP_EST,
x: ft.x,
y: ft.y,
radius: r(ft.properties.POP_EST),
startAngle: 0,
endAngle: tau,
padAngle: 0,
value: 1
}

})
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("overflow", "visible");
svg.selectAll(".country")
.data(world.features)
.enter().append("path")
.attr("class", "country")
.attr("d", path)
.attr("fill", "#f5f5f5")
.attr("opacity", 0.7)
.attr("stroke", "#e0e0e0")
.style("display", show === "show" ? "block" : "none");

svg.selectAll('path.base')
.data(bases)
.join('path')
.attr('class', "base")
.attr('transform', function(d) { return 'translate(' + [d.x, d.y] + ')'; })
.attr("fill", "#d6d6d6")
.attr("d", d => d3.arc().innerRadius(d.radius * 0.67).outerRadius(d.radius - 1)(d));

svg.selectAll('path.filled')
.data(fills)
.join('path')
.attr('class', "filled")
.attr('transform', function(d) { return 'translate(' + [d.x, d.y] + ')'; })
.attr("fill", d => colorScale(d.value))
.attr("d", d => d3.arc().innerRadius(d.radius * 0.67).outerRadius(d.radius - 1)(d));

// svg.append("g")
// .attr("transform", `translate(0, ${height - 150})`)
// .call(legend);
return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
legend = legendCircle()
.tickValues([50e6, 200e6, 500e6, 1000e6])
.tickFormat((d, i, e) => {
const val = d >= 1e9 ? `${d / 1e9}B` : `${d / 1e6}M`;
const unit = i === e.length - 1 ? " people" : "";
return `${val}${unit}`;
})
.scale(r);
Insert cell
simulation = d3.forceSimulation(world.features)
.force("x", d3.forceX(d => projection(d.centroid)[0]))
.force("y", d3.forceY(d => projection(d.centroid)[1]))
.force("collide", d3.forceCollide(d => 1 + r(d.properties.POP_EST)))
.stop();
Insert cell
Insert cell
height = width * .49;
Insert cell
Insert cell
path = d3.geoPath(projection);
Insert cell
projection = d3.geoEqualEarth()
.rotate([-10, 0, 0])
.fitSize([width, height], { type: "Sphere" });
Insert cell
Insert cell
r = d3.scaleSqrt()
.domain([0, d3.max(world.features, d => d.properties.POP_EST)])
.range([0, Math.sqrt(width * height) / 10])
Insert cell
colorScale = d3.scaleSequential(d3.interpolateYlOrRd).domain([0, 1])
Insert cell
Insert cell
tau = 2 * Math.PI
Insert cell
Insert cell
d3 = require("d3@6")
Insert cell
topojson = require("topojson-client@3");
Insert cell
import { checkbox } from "@jashkenas/inputs";
Insert cell
import { legendCircle } from "@harrystevens/circle-legend";
Insert cell
import { toc } from "@harrystevens/toc";
Insert cell
Insert cell
// Find the centroid of the largest polygon
centroid = (feature) => {
const geometry = feature.geometry;
if (geometry.type === "Polygon"){
return d3.geoCentroid(feature);
}
else {
let largestPolygon = {}, largestArea = 0;
geometry.coordinates.forEach(coordinates => {
const polygon = { type: "Polygon", coordinates },
area = d3.geoArea(polygon);
if (area > largestArea) {
largestPolygon = polygon;
largestArea = area;
}
});
return d3.geoCentroid(largestPolygon);
}
}
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