function zoomableElement(context, element, {
transformOrigin = "0 0",
scaleExtent = [.1, 4],
} = {}) {
if(transformOrigin) element.style.transformOrigin = transformOrigin;
const zoom = d3.zoom()
.scaleExtent(scaleExtent)
.constrain(constrain)
.on("zoom", onZoom);
d3.select(context)
.call(zoom)
.on("dblclick.zoom", null)
.on("wheel", e => e.preventDefault(), {passive: false});
return element;
function constrain(transform, extent, translateExtent) {
const cw = element.clientWidth;
const ch = element.clientHeight;
const dx0 = transform.invertX(extent[0][0]) - translateExtent[0][0];
const dx1 = transform.invertX(extent[1][0]) - translateExtent[1][0];
const dy0 = transform.invertY(extent[0][1]) - translateExtent[0][1];
const dy1 = transform.invertY(extent[1][1]) - translateExtent[1][1];
return transform.translate(
dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1),
dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1)
);
}
function onZoom({transform: {x, y, k}}) {
element.style.transform = `translate(${x}px,${y}px) scale(${k})`;
}
}