map = {
const cx = width / 2;
const cy = height / 2;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "middle")
.attr("fill", "currentColor")
.style("margin", "0 -14px")
.style("color", "white")
.style("background", "radial-gradient(#081f2b 0%, #061616 100%)")
.style("display", "block");
svg.append("path")
.attr("d", path(graticule))
.attr("fill", "none")
.attr("stroke", "currentColor")
.attr("stroke-opacity", 0.2);
svg.append("path")
.attr("d", path(outline))
.attr("fill", "none")
.attr("stroke", "currentColor");
svg.append("g")
.call(xAxis);
svg.append("g")
.call(yAxis);
const focusDeclination = svg.append("circle")
.attr("cx", cx)
.attr("cy", cy)
.attr("fill", "none")
.attr("stroke", "yellow");
const focusRightAscension = svg.append("line")
.attr("x1", cx)
.attr("y1", cy)
.attr("x2", cx)
.attr("y2", cy)
.attr("stroke", "yellow");
svg.append("g")
.attr("stroke", "black")
.selectAll("circle")
.data(data)
.join("circle")
.attr("r", d => radius(d.magnitude))
.attr("transform", d => `translate(${projection(d)})`);
svg.append("g")
.attr("pointer-events", "all")
.attr("fill", "none")
.selectAll("path")
.data(data)
.join("path")
.on("mouseover", mouseovered)
.on("mouseout", mouseouted)
.attr("d", (d, i) => voronoi.renderCell(i))
.append("title")
.text(formatTitle);
function mouseovered(event, d) {
const [px, py] = projection(d);
const dx = px - cx;
const dy = py - cy;
const a = Math.atan2(dy, dx);
focusDeclination.attr("r", Math.hypot(dx, dy));
focusRightAscension.attr("x2", cx + 1e3 * Math.cos(a)).attr("y2", cy + 1e3 * Math.sin(a));
}
function mouseouted(event, d) {
focusDeclination.attr("r", null);
focusRightAscension.attr("x2", cx).attr("y2", cy);
}
return svg.node();
}