map = function(routes, localWidth){
if(localWidth === undefined) {
localWidth = width
}
const height = localWidth * 0.7;
const projection = d3.geoConicConformal()
.parallels([35, 65])
.rotate([-5, 0])
.scale(localWidth * 1.3)
.center([10, 50])
.translate([localWidth / 2, height / 2])
.clipExtent([[0, 0], [localWidth, height]])
.precision(0.2)
const context = DOM.context2d(localWidth, height);
const path = d3.geoPath(projection, context);
const graticule = d3.geoGraticule10();
context.beginPath(), path(graticule), context.strokeStyle = "#ccc", context.stroke();
context.beginPath(), path(countries), context.strokeStyle = "#555", context.fillStyle = "rgba(0, 0, 0, .8)", context.fill(), context.stroke();
for (const [name, city] of Object.entries(cities)) {
context.beginPath(), path({type: "Point", coordinates: [city.longitude, city.latitude]}), path.pointRadius(2), context.fillStyle = "#a55", context.fill();
}
context.beginPath(), pathOfRoutes(routes, context, projection), context.strokeStyle = "#aaf", context.lineWidth = 2, context.stroke()
return context.canvas;
}