Public
Edited
Nov 10, 2022
1 star
Insert cell
Insert cell
chart = {
console.clear();
const width = 975;
const height = 610;

const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

const usStatesGroup = svg
.append("g")
.attr("fill", "#444")
.attr("cursor", "pointer")
.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.join("path")
.on("click", clicked)
.attr("d", path);

const zoom = d3.zoom().scaleExtent([1, 8]).on("zoom", zoomed);
zoom(svg); // now zoom listens for events that occur on SVG

function clicked(event, d) {
// Use d3.geoPath's method to get the bounding box around the path
const [[x0, y0], [x1, y1]] = path.bounds(d);
event.stopPropagation();
usStatesGroup.transition().style("fill", null); // clear highlighted paths (if any)
d3.select(this).transition().style("fill", "red"); // set "this" clicked path to be red

// Wh? In "zoomed()" we're applying transforms to usStatesGroup -- why transition "svg" here?
const newTranstition = svg.transition().duration(750);

// zoom.transform(selectionOrTransition, transform[, pointToCenterOn])
zoom.transform(
newTranstition,
// CONTEXT: the "identity X" usually means "a transformation that doesn't change what it's applied to"
// Here, zoomIdentity says "begin with a transformation matrix that does nothing, then update
// that matrix to with this transform, and this scale."
d3.zoomIdentity
.translate(width / 2, height / 2) // recenter the svg
.scale(
// Basically, zoom in as *little* as neeeded to fit the path in a square viewport
Math.min(8, 0.9 / Math.max((x1 - x0) / width, (y1 - y0) / height))
)
.translate(-(x0 + x1) / 2, -(y0 + y1) / 2) // center the clicked US state
);
}

function zoomed(event) {
const { transform } = event;
usStatesGroup.attr("transform", transform);
}

return svg.node();
}
Insert cell
path = d3.geoPath()
Insert cell
us = FileAttachment("states-albers-10m.json").json()
Insert cell
topojson = require("topojson-client@3")
Insert cell
d3 = require("d3@7")
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