Public
Edited
Feb 15, 2023
31 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
world = d3.json("https://cdn.jsdelivr.net/npm/visionscarto-world-atlas@0.1.0/world/110m.json")
Insert cell
land = topojson.feature(world, world.objects.land)
Insert cell
function createMap() {
const height = Math.round(Math.min(500, width * 0.7));
const projection = d3
.geoOrthographic()
.fitSize([width, height], { type: "Sphere" });

const context = DOM.context2d(width, height);
const path = d3.geoPath(projection, context);

function update(points, r) {
const pts = {
type: "MultiPoint",
coordinates: points.filter((d) => !d.ignore)
};

context.clearRect(0, 0, width, height);

// back face - see https://observablehq.com/@d3/projection-reflectx
context.beginPath();
projection.reflectX(true).rotate([r[0] + 180, -r[1], -r[2]]);
path.pointRadius(0.5);
path(pts);
context.fill();

// front face
context.beginPath();
projection.reflectX(false).rotate(r);
path.pointRadius(1.4);
path(pts);
context.fill();
}

context.canvas.update = update;
return context.canvas;
}
Insert cell
chart.update(points, [(now / 200) % 360, -25, 0])
Insert cell
points = {
replay;
const projection = d3.geoEqualEarth().fitWidth(width, { type: "Sphere" });
const points = d3.shuffle(
pick2d(width, width, N, "poisson")
.map((d) => {
const p = projection.invert(d);
const r = projection(p);
if (Math.hypot(r[0] - d[0], r[1] - d[1]) < 0.1) return p;
})
.filter((d) => d)
);
yield points;

let i = 0;
for (const d of points) {
if (d3.geoContains(land, d)) {
d.ignore = true;
}
if (i++ % 50 === 0) yield points;
}
yield points;
}
Insert cell
N = 20000
Insert cell
import { pick2d } from "@fil/2d-point-distributions"
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