Public
Edited
Feb 5, 2023
Insert cell
Insert cell
Insert cell
viewof c = Select(curves, {
label: "Choose a curve",
format: x => x.name,
value: curves.find(t => t.name === "curveCatmullRom")
})
Insert cell
Insert cell
map = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("width", "100%")
.style("height", "auto");

svg
.append("g")
.append("path")
.datum(sphere)
.attr("class", "graticuleOutline")
.attr("d", path)
.style("fill", "#9ACBE3");

svg
.append("g")
.append("path")
.datum(d3.geoGraticule10())
.attr("class", "graticule")
.attr("d", path)
.attr("clip-path", "url(#clip)")
.style("fill", "none")
.style("stroke", "white")
.style("stroke-width", 0.8)
.style("stroke-opacity", 0.5)
.style("stroke-dasharray", 2);

// Basemap

svg
.append("path")
.datum(countries)
.attr("fill", "#d4c9b2")
.attr("stroke", "white")
.attr("stroke-width", 0.4)
.attr("d", path);

// Coast

svg
.append("path")
.datum(coast)
.attr("fill", "none")
.attr("stroke", "#6caee0")
.attr("stroke-width", 1.5)
.attr("d", path);

// Route

const line = d3
.line()
.x((d) => d.x)
.y((d) => d.y)
.curve(c.value);

const route = svg
.append("path")
.datum(data)
.attr("d", line)
.attr("stroke", "#8c2a79")
.attr("stroke-width", 3)
.attr("stroke-dasharray", 4)
.attr("fill", "none");

// Steps

const steps = svg
.append("g")
.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", (d) => d.x)
.attr("cy", (d) => d.y)
.attr("stroke", "#8c2a79")
.attr("stroke-width", 3)
.attr("fill", "#d4c9b2")
.attr("r", 6);

// Labels

const labels = svg
.append("g")
.selectAll("text")
.data(data)
.join("text")
.attr("x", (d, i) => d.x + dx[i])
.attr("y", (d, i) => d.y + dy[i])
.attr("font-family", "sans-serif")
.attr("fill", "#8c2a79")
.attr("text-anchor", "middle")
.text((d) => d.id);

// Texts

svg
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", 70)
.attr("fill", "white")
.attr("fill-opacity", 0.5);

svg
.append("text")
.attr("x", 20)
.attr("y", 47)
.attr("font-weight", "bold")
.attr("font-family", "sans-serif")
.attr("fill", "#8c2a79")
.style("font-size", "37px")
.text(title);

svg
.append("g")
.selectAll("text")
.data(note)
.join("text")
.attr("transform", (d, i) => `translate(${20},${i * 20})`)
.attr("dy", 110)
.text((d) => d)
.attr("font-family", "sans-serif")
.attr("fill", "#8c2a79")
.style("font-size", "17px");

svg
.append("svg:a")
.attr(
"xlink:href",
"https://twitter.com/neocartocnrs/status/1318807216145813505"
)
.append("svg:text")
.text("[view original map]")
.attr("dy", 210)
.attr("dx", 20)
.attr("font-family", "sans-serif")
.attr("fill", "#8c2a79")
.style("font-size", "14px");

svg
.append("path")
.attr("d", signature)
.attr("transform", "translate(925,865) scale(1.2) ")
.attr("fill", "#8c2a79")
.attr("fill-opacity", 0.75);

// Dot Motion

const dot = svg.append("g");

while (true) {
const length = route.node().getTotalLength(),
int = d3.interpolate(0, length),
x = (t) => route.node().getPointAtLength(int(t)).x,
y = (t) => route.node().getPointAtLength(int(t)).y;

dot
.selectAll("circle")
.data([data[0]])
.join("circle")
.attr("cx", (d) => d.x)
.attr("cy", (d) => d.y)
.attr("fill", "#8c2a79")
.attr("r", 10)
.transition()
.delay(500)
.duration(10000)
.attrTween("cx", () => x)
.attrTween("cy", () => y);

yield svg.node();
await Promises.tick(12000);
}

//return svg.node();
}
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
Insert cell
locations = [
{ location: "Yaounde", lat: 3.848095197247253, lng: 11.520071138371495 },
{ location: "Bamako", lat: 12.633964541945208, lng: -8.000309963809848 },
{ location: "Tamanraset", lat: 22.91657158674978, lng: 5.570070309024585 },
{ location: "Zouara", lat: 32.93170607316592, lng: 12.089533196278982 },
{ location: "Pozzalo", lat: 36.73202975800555, lng: 14.848012527971918 },
{ location: "Rome", lat: 41.885411336120626, lng: 12.498873695199565 },
{ location: "Montpellier", lat: 43.612499290490845, lng: 3.8660941822119277 },
{ location: "Caen", lat: 49.1878709474997, lng: -0.3715700761391713 }
]
Insert cell
Insert cell
Insert cell
data = locations.map(d => ({
id: d.location,
x: projection([d.lng, d.lat])[0],
y: projection([d.lng, d.lat])[1]
}))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
d3 = require("d3@6", "d3-geo-projection@2")
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