You’re not allowed to have circular cell definitions. You can’t have a zoom
cell that depends on the svg
cell (to set the “transform” attribute via selection.attr) and an svg
cell that depends on the zoom
cell (to apply the zoom behavior via selection.call).
You could define a standalone zoom
behavior without an event listener:
zoom = d3.zoom()
.scaleExtent([1, 18])
.translateExtent([[0,0], [width, height]])
But then you have to modify the zoom
instance inside the svg
cell to add your zoom event listener, which isn’t clean. You could go the opposite way and have the zoom
cell modify the svg
element, but that isn’t very clean either (and requires removing the viewof
from your svg
definition):
{
const s = d3.select(svg);
s.call(d3.zoom()
.on("zoom", () => s.select(".map-layers").attr("transform", d3.event.transform))
.scaleExtent([1, 18])
.translateExtent([[0,0], [width, height]]));
}
If you want to break this out into a separate cell, I’d probably do that by wrapping it in a function rather than using mutation, because the relationship between these two objects (the behavior and the selection) is inherently circular.
function zoom(svg) {
svg.call(d3.zoom()
.on("zoom", () => svg.select(".map-layers").attr("transform", d3.event.transform))
.scaleExtent([1, 18])
.translateExtent([[0,0], [width, height]]));
}
Then you can enable your zoom behavior in the svg
cell simply as svg.call(zoom).