globe = function(
projection,
title,
{ invalidation, visibility, width = 300, height = 300 } = {}
) {
const context = context2d(width, height),
path = d3
.geoPath()
.projection(
projection
.precision(0.1)
.fitSize([width - 4, height - 4], { type: "Sphere" })
)
.context(context);
projection.translate(projection.translate().map(d => d + 2));
function drawText(text) {
context.save();
context.translate(4, 14);
context.font = "bold 9pt sans-serif";
context.shadowBlur = 3;
context.strokeStyle = context.shadowColor = "white";
context.shadowOffs = 0;
context.strokeText(text, 0, 0);
context.fillText(text, 0, 0);
context.restore();
}
function draw() {
const r = projection.rotate();
context.clearRect(0, 0, width, height);
context.beginPath();
path(d3.geoGraticule10());
context.lineWidth = 0.25;
context.stroke();
context.beginPath();
path(land);
context.fill();
context.beginPath();
path({ type: "Sphere" });
context.lineWidth = 1.5;
context.stroke();
drawText(title);
}
return d3
.select(context.canvas)
.classed("globe", true)
.call(
zoom(projection, draw, {
target: context.canvas,
invalidation,
visibility
})
)
.on("pointerenter pointerdown pointerup", event => {
d3.select(event.currentTarget).style(
"cursor",
event.type === "pointerdown" ? "grabbing" : "grab"
);
})
.node();
}