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) : ""}
<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;
}