function map() {
const renderer = new THREE.WebGLRenderer();
const size = Math.max(width, height);
renderer.setSize(width, height);
renderer.setPixelRatio(devicePixelRatio);
projection.fitExtent([[10, 10], [width - 10, height - 10]], {
type: "Sphere"
});
const scene = new THREE.Scene();
const mesh = new THREE.Mesh(
new THREE.SphereBufferGeometry(1, 32, 32),
new THREE.MeshBasicMaterial({ map: image })
);
scene.add(mesh);
invalidation.then(() => renderer.dispose());
const context = DOM.context2d(width, height),
canvas = context.canvas,
path = d3.geoPath(projection, context);
function render() {
const fov = 2 * Math.atan(height / projection.scale() / (D - 1) / 2),
camera = new THREE.PerspectiveCamera(
fov * (180 / Math.PI),
width / height,
0.01,
1000
);
camera.position.x = D;
camera.lookAt(new THREE.Vector3(0, 0, 0));
const a = projection.rotate();
mesh.rotation.x = (a[2] || 0) * radians;
mesh.rotation.y = a[0] * radians;
mesh.rotation.z = a[1] * radians;
mesh.rotation.order = "XZY";
renderer.render(scene, camera);
const t = projection.translate();
renderer.domElement.style.left = `${t[0] - width / 2}px`;
renderer.domElement.style.top = `${t[1] - height / 2}px`;
context.clearRect(0, 0, width, width);
context.beginPath();
context.strokeStyle = "lightblue";
path({ type: "Sphere" });
path(land);
context.stroke();
}
const div = d3.create("div");
div.node().appendChild(renderer.domElement);
div.node().appendChild(canvas);
div.node().style.height = `${height}px`;
canvas.style.position = "absolute";
canvas.style.left = 0;
renderer.domElement.style.position = "absolute";
div.node().style.overflow = "hidden";
return div
.call(
zoom(projection)
.on("zoom.render", render)
.on("end.render", render)
)
.call(render)
.node();
}