Public
Edited
Nov 24, 2022
2 forks
21 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
world = FileAttachment("ne_110m_admin_0_countries_lakes.json").json();
Insert cell
worldGeo = {
const json = topojson.feature(world, world.objects.ne_110m_admin_0_countries_lakes);
json.features.forEach(d => {
d.base = base(d);
return;
});
return json;
};
Insert cell
Insert cell
size = Math.min(600, width);
Insert cell
Insert cell
projection = d3.geoOrthographic()
.fitSize([size, size], { type: "Sphere" })
Insert cell
path = d3.geoPath(projection);
Insert cell
Insert cell
d3 = require("d3-array@2", "d3-geo@1", "d3-inertia@0.1.0", "d3-scale@3", "d3-selection@1")
Insert cell
geometric = require("geometric@2");
Insert cell
polylabel = require('https://bundle.run/polylabel@1.1.0');
Insert cell
topojson = require("topojson@3");
Insert cell
import { toc } from "@harrystevens/toc";
Insert cell
Insert cell
height = d3.scaleLinear()
.domain([0, d3.max(worldGeo.features, d => d.properties.POP_EST)])
.range([0, 200]);
Insert cell
Insert cell
styles = `
.globe {
display: table;
margin: 0 auto;
overflow: visible;
}
.country {
fill: #e0e0e0;
stroke: #ccc;
stroke-linejoin: round;
}
.sphere {
fill: none;
stroke: #ccc;
stroke-width: 2px;
}
.spike {
fill: red;
fill-opacity: 0.3;
stroke: red;
transition: opacity 350ms;
}
.spike.fast-fade {
transition: opacity 150ms;
}
.spike.hide {
opacity: 0;
}
`
Insert cell
Insert cell
function base(d){
const c = d.geometry.coordinates;
if (d.geometry.type === "Polygon"){
return polylabel(c);
}
else {
let largestArea = 0, largestIndex = -1;
for (let i = 0, l = c.length; i < l; i++){
const area = d3.geoArea({ type: "Polygon", coordinates: c[i] });
if (area > largestArea){
largestArea = area;
largestIndex = i;
}
}
return polylabel(c[largestIndex]);
}
}
Insert cell
function spike(){
let x = 0,
y = 0,
width = 0,
height = 0,
angle = -90,
closed = false;
function spike(datum){
const dx = typeof x === "function" ? x(datum) : x,
dy = typeof y === "function" ? y(datum) : y,
dwidth = typeof width === "function" ? width(datum) : width,
dheight = typeof height === "function" ? height(datum) : height,
dangle = typeof angle === "function" ? angle(datum) : angle,
base = [dx, dy],
a = geometric.pointTranslate(base, dangle - 90, dwidth / 2),
b = geometric.pointTranslate(base, dangle, dheight),
c = geometric.pointTranslate(base, dangle + 90, dwidth / 2);

return closed ? [a, b, c, a] : [a, b, c];
}
spike.x = function(n){ return arguments.length ? (x = n, spike) : x; }
spike.y = function(n){ return arguments.length ? (y = n, spike) : y; }
spike.width = function(n){ return arguments.length ? (width = n, spike) : width; }
spike.height = function(n){ return arguments.length ? (height = n, spike) : height; }
spike.angle = function(n){ return arguments.length ? (angle = n, spike) : angle; }
spike.closed = function(b){ return arguments.length ? (closed = b, spike) : closed; }
return spike;
}
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