Public
Edited
Jun 3, 2024
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
image = {
// For brevity we create the elements through htl instead of d3.
// We'll wrap them in d3.select(element) whenever we require a d3 selection.
const svg = htl.svg`<svg width=600 height=500 style="border:1px solid #aaa">`;
// This group will be the transform target to which we add our data points.
const points = htl.svg`<g>`;
// This rect will become the area in which the most recent point needs to be visible.
const frame = htl.svg`<rect x=150 y=150 width=300 height=200 stroke="#0008" fill="#0001" />`;
svg.append(frame, points);

// A helper to get the [left, top, right, bottom] bxtent for an SVG element.
// Optionally we can pass sx() and sy() to scale the offsets.
function extent(element, sx = d => d, sy = d => d) {
const {x, y, width, height} = element.getBBox();
return [sx(x), sy(y), sx(x + width), sy(y + height)];
}
svg.addEventListener("click", e => {
const [x, y] = d3.pointer(e, points);
const element = htl.svg`<circle cx=${x} cy=${y} r=5 fill=black />`;
points.append(element);
// Fade out points and remove them after a while.
d3.select(element).transition().duration(10000).attr("fill", "#0000").remove();

const t = d3.zoomTransform(svg);
const [ax0, ay0, ax1, ay1] = extent(frame, x => t.invertX(x), y => t.invertY(y));
const [bx0, by0, bx1, by1] = extent(element);

const dx = bx0 < ax0 ? ax0 - bx0 : bx1 > ax1 ? ax1 - bx1 : 0;
const dy = by0 < ay0 ? ay0 - by0 : by1 > ay1 ? ay1 - by1 : 0;
if(dx || dy) {
// We pass a transition so that d3-zoom will automatically animate the change.
const transition = d3.select(svg).transition().delay(150).duration(250).ease(d3.easeCubicOut);
zoom.translateBy(transition, dx, dy);
}
});

const zoom = d3.zoom().on("zoom", ({transform}) => {
d3.select(points).attr("transform", transform);
});
d3.select(svg).call(zoom);
svg.zoom = zoom;
return svg;
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more