viewof value = {
const margin = 40;
const x = d3.scaleLinear([-5000, 5000], [margin, width - margin]);
const y = d3.scaleLinear([-5000, 5000], [margin, height - margin]);
const svg = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height]);
svg
.append("g")
.attr("transform", `translate(0,${height - margin})`)
.call(d3.axisBottom(x))
.call((g) =>
g
.selectAll(".tick line")
.clone()
.attr("y2", 2 * margin - height)
.attr("stroke-opacity", 0.2),
);
svg
.append("g")
.attr("transform", `translate(${width - margin},0)`)
.call(d3.axisRight(y))
.call((g) =>
g
.selectAll(".tick line")
.clone()
.attr("x2", 2 * margin - width)
.attr("stroke-opacity", 0.2),
);
const dot = svg.append("g")
.attr("display", "none");
dot.append("circle").attr("r", 3).attr("fill", "black");
svg
.on("pointerenter", pointerentered)
.on("pointermove", pointermoved)
.on("pointerleave", pointerleft)
.on("touchstart", (event) => event.preventDefault());
function pointerentered() {
dot.attr("display", null);
}
function pointermoved(event) {
const [xm, ym] = d3.pointer(event);
dot.attr("transform", `translate(${xm},${ym})`);
}
function pointerleft() {
dot.attr("display", "none");
}
return svg.node();
}