Public
Edited
Jun 16, 2023
1 fork
6 stars
Insert cell
Insert cell
Insert cell
chart = {
const height = 600;
const cx = width / 2;
const cy = height / 2;

// This projection is baked into the TopoJSON file; it is
// used here to compute the desired zoom translate.
const projection = d3.geoMercator().translate([0, 0]).scale(4000);
const sf = projection([-122.417, 37.775]);
const ny = projection([-74.0064, 40.7142]);
const i = d3.interpolateZoom([...sf, 400], [...ny, 600]);

let transform;
let visibleArea; // minimum area threshold for points inside viewport
let invisibleArea; // minimum area threshold for points outside viewport

const simplify = d3.geoTransform({
point(x, y, z) {
if (z < visibleArea) return;
x = transform.applyX(x);
y = transform.applyY(y);
if (x >= -10 && x <= width + 10 && y >= -10 && y <= height + 10 || z >= invisibleArea) this.stream.point(x, y);
}
});

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

function update(t) {
const [tx, ty, w] = i(t);
transform = d3.zoomIdentity.translate(cx, cy).scale(width / w).translate(-tx, -ty);
visibleArea = 1 / (transform.k * transform.k);
invisibleArea = 200 * visibleArea;
context.clearRect(0, 0, width, height);
context.beginPath();
path(mesh);
context.stroke();
}

return Object.assign(context.canvas, {update});
}
Insert cell
chart.update(t)
Insert cell
mesh = topojson.mesh(us)
Insert cell
us = topojson.presimplify(await FileAttachment("us-states.json").json())
Insert cell
topojson = require("topojson-client@3", "topojson-simplify@3")
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