Public
Edited
Feb 21, 2024
6 forks
22 stars
Contour Labels (canvas)Coordinated mapsgeoformatSmall circle testKruskal MazeAll the geoshapesReprojecting Vector TilesCloud ContoursHello h3-jsClipping AlbersTranslucent EarthThe truth about the Mercator projectionUsing d3-inertia with observableMercator projection of a Mercator globeD3 Vector Tiles (WIP)Finding intersections between the graticule and the clip sphere of the stereographic projection, method 2Plate tectonicsAnother hex mapEquateur & tropiquesTissot's indicatrixDistance to shoreMultiPolygon clippingSouth Africa’s medial axisSpherical intersectionVolcano Semis (points circulaires)Pencil Airocean45° mapNetCDFBlue noise sphereRubber DymaxionSpherical quasi-random (R2) distributionAutomated label placement (countries)Automated label placement (France)Automated label placement (cities)d3.geoIntersectArcDelaunay.findTriangled3-geo-voronoi and gridded dataElevation vtk.jsMapfillKrigingSpherical HeatmapReproject elevation tiles — detailReproject elevation tiles — worldFisheye Conformal MapSpherical KDE InterpolationSpherical kernel interpolation with nearest neighborsShepard’s methodModified Shepard’s methodSpherical contoursGeo Voronoi interpolationBlurry contoursHow much warmer? (BBC)H3 hexagons & geoContoursHillshading & supersampling
H3 oddities
Manhattan VoronoiManhattan Voronoi IIGeoJSON feature editorColorized Manhattan Spanning Treelegra mapslegra country mapsThe complex logarithm projectionCountries small multipleThe 2D approximate Newton-Raphson methodOceanAttitudeCount visible objectsThe Gray-Fuller spatial gridGray-Fuller grid metricsGray-Fuller grid odditiesSpherical smallest-circle problemBounding CirclesCountries Enclosing CirclesFullscreen Seamless Zoomable Map TilesMap Pan & ZoomSpherical EllipsesSynchronized projectionsThe closest countryTriangular tiling of icosahedronHello, polygon-clippingCorées / KoreasHello, procedural-glHello, placekeyZoom World ChoroplethClipping spherical polygonsSpherical phyllotaxisFour-color world map with ClingoHello, jsgeoda!The Sun’s analemmaWorld of squaresWorld of squares (spherical)A map of AfricaTagged bordersClipped geoVoronoiBlue noise sphere IISpherical Perlin NoiseSpherical Delaunay triangulationDynamic simplificationRewindPlot: Voronoi labelsAoC 12: shortest path under constraintsHello, pixi.jsFlight PathsRay out of a convex hullDistance to a segmentHello, A5
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
h3 = import("h3-js@4")
Insert cell
hexworld = level => ({
type: "FeatureCollection",
features: h3.getRes0Cells()
.map(i => h3.cellToChildren(i, level))
.flat()
.map(d => ({
type: "Feature",
properties: { id: d, pentagon: h3.isPentagon(d) },
geometry: {
type: "Polygon",
coordinates: [h3.cellToBoundary(d, true).reverse()]
}
}))
})
Insert cell
hexagons = hexworld(resolution)
Insert cell
contours = d3
.geoContour()
.x(d => d3.geoCentroid(d)[0])
.y(d => d3.geoCentroid(d)[1])
.value((d, i) => 10 * Math.log10(areas[i] / median))
.thresholds(100)(hexagons.features)
Insert cell
areas = hexagons.features.map(d => d3.geoArea(d))
Insert cell
median = d3.median(areas)
Insert cell
color = d3.scaleSequential(t => d3.interpolateRdYlGn(1 - t)).domain([-1, 1])
Insert cell
function chart() {
const context = DOM.context2d(width, height),
path = d3.geoPath(projection).context(context);

context.beginPath();
path({ type: "Sphere" });
context.fillStyle = color(0);
context.fill();
context.lineWidth = 3;
context.stroke();
context.clip();
context.lineWidth = 0.5;

for (const c of contours) {
context.beginPath();
path(c);
context.strokeStyle = context.fillStyle = color(c.value);
context.fill();
context.stroke();
}

context.beginPath();
context.fillStyle = "lightblue";
for (const penta of hexagons.features.filter(d => d.properties.pentagon))
path(penta);
context.fill();

context.beginPath();
for (const hepta of hexagons.features.filter(
d => d.geometry.coordinates[0].length == 8
)) {
path({ type: "Point", coordinates: d3.geoCentroid(hepta) });
}
context.fillStyle = "red";
context.fill();

context.beginPath();
context.fillStyle = "black";
for (const octo of hexagons.features.filter(
d => d.geometry.coordinates[0].length == 9
))
path({ type: "Point", coordinates: d3.geoCentroid(octo) });
context.fill();

context.beginPath();
context.fillStyle = "lightblue";
for (const nona of hexagons.features.filter(
d => d.geometry.coordinates[0].length == 10
))
path({ type: "Point", coordinates: d3.geoCentroid(nona) });
context.fill();

context.beginPath();
context.fillStyle = "darkorange";
for (const deca of hexagons.features.filter(
d => d.geometry.coordinates[0].length == 11
))
path({ type: "Point", coordinates: d3.geoCentroid(deca) });
context.fill();

context.strokeStyle = "#fff";
context.beginPath();
path(hexagons);
context.lineWidth = 0.5;
context.stroke();

context.strokeStyle = "black";
context.beginPath();
path(land);
context.lineWidth = 1.5;
context.stroke();

return context.canvas;
}
Insert cell
d3 = require("d3@7", "d3-geo-voronoi@2", "d3-geo-polygon@1.8")
Insert cell
land = {
const world = await fetch("https://cdn.jsdelivr.net/npm/visionscarto-world-atlas@0.1.0/world/110m.json").then(d => d.json());
return topojson.feature(world, world.objects.countries);
}
Insert cell
projection = ({
Airocean: d3
.geoAirocean()
.angle(-150)
.fitExtent([[2, 2], [width - 2, height - 2]], { type: "Sphere" }),
"Gnomonic icosahedral": d3
.geoIcosahedral()
.faceProjection(face => {
const c = face.site.map(d => -d);
c[2] = Math.abs(c[1] - 52.62) < 1 || Math.abs(c[1] + 10.81) < 1 ? 60 : 0;
return d3
.geoProjection(d3.geoGnomonicRaw)
.rotate(c)
.translate([0, 0]);
})
.rotate([-83.65929, 25.44458, -87.45184])
.angle(60)
.fitExtent([[2, 2], [width - 2, height - 2]], { type: "Sphere" }),
"Gray-Fuller icosahedral": d3
.geoIcosahedral()
.faceProjection(face => {
var c = face.site.map(d => -d);
c[2] = Math.abs(c[1] - 52.62) < 1 || Math.abs(c[1] + 10.81) < 1 ? 60 : 0;
return d3
.geoProjection(d3.geoGrayFullerRaw())
.rotate(c)
.translate([0, 0]);
})
.rotate([-83.65929, 25.44458, -87.45184])
.angle(60)
.fitExtent([[2, 2], [width - 2, height - 2]], { type: "Sphere" }),
Orthographic: d3
.geoOrthographic()
.rotate([-110, -35])
.fitExtent([[2, 2], [width - 2, height - 2]], { type: "Sphere" }),
"Azimuthal equal-area": d3
.geoAzimuthalEqualArea()
.rotate([-110, -35])
.clipAngle(54)
.fitExtent([[2, 2], [width - 2, height - 2]], { type: "Sphere" }),
Mercator: d3
.geoMercator()
.fitExtent([[2, 2], [width - 2, height - 2]], { type: "Sphere" })
}[projname])
Insert cell
height = (width * (projname === "Airocean" ? 2.1 : 1)) | 0
Insert cell
import { legend } from "@d3/color-legend"
Insert cell
import { select } 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