Published
Edited
Jun 30, 2021
Importers
6 stars
Insert cell
Insert cell
viewof worldMap1 = worldMapCoordinates([-122.27, 37.87])
Insert cell
function worldMapCoordinates(config = {}) {
const {
value = [], title, description, width = 400
} = Array.isArray(config) ? {value: config} : config;
const height = Math.round((210 / 400) * width);
let [lon, lat] = value;
lon = lon != null ? lon : null;
lat = lat != null ? lat : null;
const formEl = html`<form style="width: ${width}px;"></form>`;
const context = DOM.context2d(width, height);
const canvas = context.canvas;
canvas.style.margin = "10px 0 3px";
const projection = d3
.geoNaturalEarth1()
.precision(0.1)
.fitSize([width, height], { type: "Sphere" });
const path = d3.geoPath(projection, context).pointRadius(2.5);
formEl.append(canvas);

function draw() {
context.fillStyle = "#fff";
context.fillRect(0, 0, width, height);
context.beginPath();
path(graticule);
context.lineWidth = 0.35;
context.strokeStyle = `#ddd`;
context.stroke();
context.beginPath();
path(land);
context.fillStyle = `#f4f4f4`;
context.fill();
context.beginPath();
path(countries);
context.strokeStyle = `#aaa`;
context.stroke();
if (lon != null && lat != null) {
const pointPath = { type: "MultiPoint", coordinates: [[lon, lat]] };
context.beginPath();
path(pointPath);
context.fillStyle = `#f00`;
context.fill();
}
}

let drag = d3.drag()
.on("drag", (event) => {
let coords = projection.invert([event.x, event.y]);
lon = +coords[0].toFixed(2);
lat = +coords[1].toFixed(2);
draw();
canvas.dispatchEvent(new CustomEvent("input", { bubbles: true }));
})

d3.select(canvas).call(drag)

canvas.onclick = function(ev) {
const { offsetX, offsetY } = ev;
let coords = projection.invert([offsetX, offsetY]);
lon = +coords[0].toFixed(2);
lat = +coords[1].toFixed(2);
draw();
canvas.dispatchEvent(new CustomEvent("input", { bubbles: true }));
};

draw();

const form = input({
type: "worldMapCoordinates",
title,
description,
display: v =>
html`<div style="width: ${width}px; white-space: nowrap; color: #444; text-align: center; font: 13px sans-serif; margin-bottom: 5px;">
<span style="color: #777;">Longitude:</span> ${lon != null ? lon.toFixed(2) : ""}
&nbsp; &nbsp;
<span style="color: #777;">Latitude:</span> ${lat != null ? lat.toFixed(2) : ""}
</div>`,
getValue: () => [lon != null ? lon : null, lat != null ? lat : null],
form: formEl
});
return form;
}
Insert cell
import { input } from "@jashkenas/inputs"
Insert cell
graticule = d3.geoGraticule10()
Insert cell
world = (await fetch("https://cdn.jsdelivr.net/npm/world-atlas@1/world/110m.json")).json()
Insert cell
land = topojson.feature(world, world.objects.land)
Insert cell
countries = topojson.feature(world, world.objects.countries)
Insert cell
topojson = require("topojson-client@3")
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