Question

I have a d3.js graph that is a forced layout design. I have allowed for users to zoom in and out of the graph with bounds set so they can't zoom in past 1 and can't zoom out past 0.1. Right now, when I plot values on the graph, I automatically send them to the center of the graph (based on the height and width of the SVG container). This works fine until I zoom out then zoom in to some where else and plot a new node. The new node will end up back at the original center and not my new relative center.

How I scale when zooming right now:

function onZoom() {
    graph.attr("transform", "translate(" + zoom.translate() + ")" + " scale(" + zoom.scale() + ")");
}

I was unable to find any calls to get the current visible coordinates of the graph, but even with those, how would I use them to calculate the relative center of the graph if my SVG graph size always remains static?

Was it helpful?

Solution 2

For simple geometric zoom, it's fairly straightforward to figure out the visible area from the visible area dimensions plus the translation and scale settings. Just remember that the translation setting is the position of the (0,0) origin relative to the top left corner of your display, so if translation is (-100,50), that means that top left corner is at (+100,-50) in your coordinate system. Likewise, if the scale is 2, that means that the visible area covers 1/2 as many units as the original width and height.

How to access the current transformation? graph.attr("transform") will give you the most recently set transform attribute string, but then you'll need to use regular expressions to access the numbers. Easier to query the zoom behaviour directly using zoom.translate() and zoom.scale().

With those together, you get

var viewCenter = [];

viewCenter[0] = (-1)*zoom.translate()[0] + (0.5) * (  width/zoom.scale() );
viewCenter[1] = (-1)*zoom.translate()[1] + (0.5) * ( height/zoom.scale() );

I.e., the position of the center of the visible area is the position of the top-left corner of the visible area, plus half the visible width and height.

OTHER TIPS

I know this post is very old but I found it useful. Below is the update for d3 v5.

var el = d3.select('#canvas').node().getBoundingClientRect();

var z = d3.zoomTransform(svg.node());
var w = el.width;
var h = el.height;

var center = {
    x: (z.x / z.k * -1) + (w / z.k * 0.5),
    y: (z.y / z.k * -1) + (h / z.k * 0.5)
};

One thing of note, however... is that I found I also needed to divide the pan x/y by the scale factor z.k. Which, you did not do in your formula.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top