Unlisted
Edited
May 29, 2023
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
height: 1200,
projection: ({ width, height }) =>
d3.geoAirocean().angle(30).fitSize([width, height], countries),
marks: [
Plot.geo(countries),
!show_ellipses
? []
: Plot.dot(
countries.features,
pole({
strokeWidth: 0.25,
poleRatio: poleRatio,

// hack to replace the circles by ellipses
render(index, scales, values, dimensions, context, next) {
const g = next(index, scales, values, dimensions, context);
for (const circle of d3.select(g).selectAll("circle")) {
circle.replaceWith(
svg`<ellipse
cx=${circle.getAttribute("cx")}
cy=${circle.getAttribute("cy")}
rx=${circle.getAttribute("r")}
ry=${circle.getAttribute("r") / poleRatio}
>`
);
}
return g;
}
})
),
Plot.text(
countries.features,
pole({
fill: "blue",
r: 2,
text: (d) => d.properties.name,
minRadius: 8,
poleRatio: poleRatio
})
)
]
})
Insert cell
polylabel = import("https://cdn.skypack.dev/polylabel@1.1.0?min").then(
(d) => d.default
)
Insert cell
pole = function ({ geometry = (d) => d, minRadius = 0, poleRatio = 1, ...options } = {}) {
const precision = 1;
return Plot.initializer(
options,
(data, facets, channels, scales, dimensions, { projection }) => {
const G = Plot.valueof(data, geometry).map((d) =>
d3.geoProject(d, projection)
);
const n = G.length;
const X = new Float64Array(n).fill(NaN);
const Y = new Float64Array(n);
const R = new Float64Array(n);
for (let i = 0; i < n; ++i) {
const { type, coordinates } =
G[i].type === "Feature" ? G[i].geometry : G[i];
const c =
type === "MultiPolygon"
? d3.greatest(
coordinates.map((polygon) => polylabelratio(polygon, precision, poleRatio)),
(c) => c.distance
)
: type === "Polygon"
? polylabelratio(coordinates, precision, poleRatio)
: [null, null];

if ((R[i] = c.distance) > minRadius) {
[X[i], Y[i]] = c;
}
}
return {
data,
facets,
channels: {
x: { value: X, source: null },
y: { value: Y, source: null },
r: { value: R, source: null }
}
};
}
);
}
Insert cell
function polylabelratio(polygon, precision, ratio) {
return ratio === 1
? polylabel(polygon, precision)
: ((d) => ((d[1] /= ratio), d))(
polylabel(
polygon.map((ring) => ring.map(([x, y]) => [x, y * ratio])),
precision
)
);
}
Insert cell
d3 = require("d3@7", "d3-geo-projection@4", "d3-geo-polygon@1.8")
Insert cell
import {countries} from "@visionscarto/geo"
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