map = {
const s = 300;
const p = s / 50;
const svg = d3.create("svg")
.attr("height", s)
.attr("width", s)
.attr("viewBox", [0, 0, s, s]);
const clipPath = svg.append("defs").append("clipPath")
.attr("id", "globe");
clipPath.append("circle")
.attr("cx", s/2)
.attr("cy", s/2)
.attr("r", s/2);
const mapImage = svg.append("image")
.attr("xlink:href", "https://upload.wikimedia.org/wikipedia/commons/5/51/BlankMap-Equirectangular.svg")
.attr("width", s*2)
.attr("height", s)
.attr("x", s/10 - offset*p)
.attr("clip-path", "url(#globe)");
for(let lineX = 0; lineX < s; lineX += p) {
svg.append("line")
.attr("x1", lineX + (offset % p))
.attr("x2", lineX + (offset % p))
.attr("y1", 0)
.attr("y2", s)
.attr("stroke", "white")
.attr("stroke-width", p/4)
.attr("clip-path", "url(#globe)");
}
for(let lineY = 0; lineY < s; lineY += p) {
svg.append("line")
.attr("x1", 0)
.attr("x2", s*2)
.attr("y1", lineY)
.attr("y2", lineY)
.attr("stroke", "white")
.attr("stroke-width", p/4)
.attr("clip-path", "url(#globe)");
}
svg.append("circle")
.attr("cx", s/2)
.attr("cy", s/2)
.attr("r", s/2 - 1)
.attr("stroke", "#000")
.attr("stroke-width", p/4)
.attr("fill", "transparent");
const poiCircle = svg.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", p/2)
.attr("opacity", 0)
.attr("fill", "red");
function convertPoi(d) {
return {
...d,
coord: [ (d.coord[0]-offset+0.5)*p, (d.coord[1]+0.5)*p ]
};
}
const convertedPoi = poi.map(convertPoi);
const filteredPoi = convertedPoi.filter(d => inCircle(d.coord[0], d.coord[1], s));
const points = filteredPoi
.map(d => d.coord)
.filter(([x, y]) => inCircle(x, y, s));
const delaunay = d3D.Delaunay.from(points);
function hidePoiCircle() {
poiCircle
.attr("opacity", 0);
}
svg.on("mousemove", () => {
const [mouseX, mouseY] = d3.mouse(svg.node());
if(!inCircle(mouseX, mouseY, s)) {
hidePoiCircle();
return;
}
const i = delaunay.find(mouseX, mouseY);
if(i === undefined || i === null || i < 0) {
hidePoiCircle();
return;
}
const place = filteredPoi[i];
if(!place) {
hidePoiCircle();
return;
}
poiCircle
.attr("cx", place.coord[0])
.attr("cy", place.coord[1]);
poiCircle
.attr("opacity", 1);
});
const wrapper = html`<div class="wrapper"></div>`;
wrapper.append(svg.node());
return wrapper;
}