Public
Edited
Nov 5, 2023
Insert cell
Insert cell
Insert cell
chart = {
style;
const svg = d3.create("svg").attr("width", width).attr("height", height);

const projection = d3.geoAlbers()
.translate([width / 2, height / 2])
.scale(width*1.2);

const radius = d3.scaleSqrt()
.domain([0, 100])
.range([0, 14]);

const path = d3.geoPath()
.projection(projection)
.pointRadius(2.5);

/*const voronoi = d3.Delaunay
.from(airports.map(projection))
.voronoi([-1, -1, width + 1, height + 1])*/

svg.append("path")
.datum(topojson.feature(us, us.objects.land))
.attr("class", "land")
.attr("d", path);

svg.append("path")
.datum(topojson.mesh(us, us.objects.states, (a, b) => a !== b ))
.attr("class", "state-borders")
.attr("d", path);

svg.append("path")
.datum({type: "MultiPoint", coordinates: airports})
.attr("class", "airport-dots")
.attr("d", path);

const airport = svg.selectAll(".airport")
.data(airports)
.join("g")
.attr("class", "airport");

airport.append("title")
.text((d) => `${d.iata}\n${d.arcs.coordinates.length} flights`);

airport.append("path")
.attr("class", "airport-arc")
.attr("d", d => path(d.arcs));

/* airport.append("path")
//.datum((_,i) => voronoi.cellPolygon(i))
.attr("class", "airport-cell")
.attr("d", (d) => d ? "M" + d.join("L") + "Z" : null)*/

return svg.node();
}
Insert cell
style = html`
<style>

.land {
fill: #ddd;
}

.state-borders {
fill: none;
stroke: #fff;
}

.airport-arc {
fill: none;
}

.airport:hover .airport-arc {
stroke: #f00;
}

.airport-cell {
fill: none;
stroke: #000;
stroke-opacity: 0.1;
pointer-events: all;
}
</style>
`
Insert cell
rawAirports = {
const airports = await FileAttachment("airports.csv").text()
.then(res => d3.csvParse(res, (d) => {
d[0] = +d.longitude;
d[1] = +d.latitude;
d.arcs = {type: "MultiLineString", coordinates: []};
return d;
}));
const flights = await FileAttachment("flights.csv").text().then(res => d3.csvParse(res, d3.autoType));
const airportByIata = new Map(airports.map(d => [d.iata,d] ));

flights.forEach((flight) => {
const source = airportByIata.get(flight.origin),
target = airportByIata.get(flight.destination);
source.arcs.coordinates.push([source, target]);
target.arcs.coordinates.push([target, source]);
});

return airports.filter((d) => d.arcs.coordinates.length);
}
Insert cell
airports = rawAirports.slice(0, maxAirports)
Insert cell
us = FileAttachment("us.json").json()
Insert cell
height = 540
Insert cell
d3 = require("d3@6", "d3-delaunay@5")
Insert cell
topojson = require("topojson")
Insert cell
import {slider} from "@jashkenas/inputs"
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