function map_it(objects, opts = {}) {
let {
w = 600,
h = w,
pad = 20,
fontSize = 14,
projection = d3.geoEquirectangular()
} = opts;
let div = d3
.create("div")
.style("width", `${w}px`)
.style("height", `${h}px`)
.style("position", "relative")
.style("background-color", "lightblue");
let svg = div
.append("svg")
.attr("viewBox", [0, 0, w, h])
.style("max-width", `${w}px`);
projection.fitExtent(
[
[pad, pad],
[w - pad, h - pad]
],
objects.boundary
);
let path = d3.geoPath().projection(projection);
let graticule = d3
.geoGraticule()
.extent([
[-180, -80],
[180, 80]
])
.step([1, 1])();
if (objects.background) {
let background = svg.append("g");
background
.selectAll("path")
.data(objects.background.features)
.join("path")
.attr("class", "land")
.attr("d", path)
.attr("fill", "#f3f3f3")
.attr("stroke", "gray")
.attr("stroke-width", 0.5);
}
let boundary = svg.append("g");
boundary
.selectAll("path")
.data(objects.boundary.features)
.join("path")
.attr("class", "land")
.attr("d", path)
.attr("fill", "lightgray")
.attr("stroke", "black")
.attr("stroke-width", 3);
if (objects.roads) {
let road_group = svg.append("g");
road_group
.append("g")
.selectAll("path")
.data(objects.roads.features)
.join("path")
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", 4)
.attr("stroke-linejoin", "round")
.attr("d", path)
.style("pointer-events", "none");
road_group
.append("g")
.selectAll("path")
.data(objects.roads.features)
.join("path")
.attr("fill", "none")
.attr("stroke", "white")
.attr("stroke-width", 2)
.attr("stroke-linejoin", "round")
.attr("d", path)
.style("pointer-events", "none");
}
if (objects.cities) {
objects.cities.features.forEach(function (o) {
let [x, y] = projection(o.geometry.coordinates);
o.properties.x = x;
o.properties.y = y;
});
let city_group = svg.append("g");
city_group
.selectAll("circle")
.data(objects.cities.features)
.join("circle")
.attr("cx", (o) => o.properties.x)
.attr("cy", (o) => o.properties.y)
.attr("r", 4)
.attr("fill", "red")
.attr("stroke", "black");
div
.append("div")
.selectAll("div")
.data(objects.cities.features)
.join("div")
.style("position", "absolute")
.style("font-size", `${fontSize}px`)
.style("left", (o) => `${o.properties.x}px`)
.style("top", (o) => `${o.properties.y}px`)
.text((o) => o.properties.Name)
.style("border", "solid 1px black")
.style("background-color", "rgba(256,256,256,0.7)");
}
return div.node();
}