Public
Edited
Dec 15, 2023
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const a = mapLastClick;
const m = chart.mapPixelsToLocations;
let val = "-";
const k = a.join("_");
if (m.has(k)) {
val = m.get(k);
}
return `${k} ${val}`;
}
Insert cell
viewof mapLastClick = chart.setLocations(locationsTwo).run().canvas
Insert cell
chart = {
const context = DOM.context2d(width, height);
const canvas = context.canvas;
const path = d3.geoPath(projection, context);
let locations = [];
const mapPixelsToLocations = new Map();
let selection;
let api;

context.canvas.addEventListener(
"click",
({ pointerId, clientX, clientY, pressure }) => {
canvas.value = [clientX, clientY];
canvas.dispatchEvent(new CustomEvent("input"));
}
);

function drawLocations() {
for (const c of locations) {
const position = projection(c);
const [x, y] = position;
mapPixelsToLocations.set(`${x}_${y}`, c);
context.strokeStyle = "tomato";
context.beginPath();
// arc(x, y, radius, startAngle, endAngle)
context.arc(x, y, 5, 0, 2 * Math.PI);
context.fillStyle = "tomato";
context.fill();
}
}

function render(land) {
context.clearRect(0, 0, width, height);
context.beginPath(),
path(sphere),
(context.fillStyle = "white"),
context.fill();
context.beginPath(),
path(land),
(context.strokeStyle = "black"),
context.stroke(),
(context.fillStyle = "aliceBlue"),
context.fill();

context.save();
drawLocations(locations);
context.restore();
}

function setLocations(locs) {
locations = locs;
return api;
}

function run() {
selection = d3
.select(context.canvas)
.call(
zoom(projection)
.on("zoom.render", () => render(countries))
.on("end.render", () => render(countries))
)
.call(() => render(countries));
return api;
}

run();

api = Object.assign(selection, {
setLocations,
run,
canvas,
mapPixelsToLocations
});

return api;
}
Insert cell
locations = [
[-79.9399309, 32.7884363], // chs
[2.1774322, 41.3828939] // bcn
]
Insert cell
locationsTwo = [
[-74.006, 40.7128], // New York City, USA
[-118.2437, 34.0522], // Los Angeles, USA
[-0.1278, 51.5074], // London, UK
[139.6917, 35.6895], // Tokyo, Japan
[151.2093, -33.8688] // Sydney, Australia
]
Insert cell
function zoom(
projection,
{
// Capture the projection’s original scale, before any zooming.
scale = projection._scale === undefined
? (projection._scale = projection.scale())
: projection._scale,
scaleExtent = [0.8, 20],
translate = projection
.translate()
.map((d) => d / (projection.scale() / scale))
} = {}
) {
const zoom = d3
.zoom()
.scaleExtent(scaleExtent.map((x) => x * scale))
.on("start", zoomstarted)
.on("zoom", zoomed);

function zoomstarted() {}

function zoomed(event) {
const { k, x, y } = event.transform;
projection
.scale(k)
.translate([
translate[0] * (k / scale) + x,
translate[1] * (k / scale) + y
]);
}

return Object.assign(
(selection) =>
selection
.property("__zoom", d3.zoomIdentity.scale(projection.scale()))
.call(zoom),
{
on(type, ...options) {
return options.length
? (zoom.on(type, ...options), this)
: zoom.on(type);
},
filter() {
return zoom.filter(...arguments), this;
}
}
);
}
Insert cell
projection = d3[projectionName]().precision(0.1)
Insert cell
sphere = ({type: "Sphere"})
Insert cell
land50 = FileAttachment("land-50m.json").json().then(world => topojson.feature(world, world.objects.land))
Insert cell
land110 = FileAttachment("land-110m.json").json().then(world => topojson.feature(world, world.objects.land))
Insert cell
topojson = require("topojson-client@3")
Insert cell
d3 = require("d3@6")
Insert cell
countries = {
const data = await FileAttachment("countries-mike@2.json").json();
return data;
}
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