Constraining map panning with zoom.translateExtent in D3 v4

醉酒当歌 提交于 2019-12-04 04:42:34

@McGiogen's solution is almost correct but misses that MIN needs to vary depending on the zoom scale factor transform.k.

I drew a diagram to see how I needed to constrain my svg to always be contained inside the zoomed view (depicted in my drawing as the LARGER of the boxes, only a portion of which is visible to the user):

(since the constraint x+kw >= w is equivalent to x >= (1-k)w, with a similar argument for y)

thus assuming your svg container size [w, h]:

function zoomed() {
    var t = d3.event.transform;

    t.x = d3.min([t.x, 0]);
    t.y = d3.min([t.y, 0]);
    t.x = d3.max([t.x, (1-t.k) * w]);
    t.y = d3.max([t.y, (1-t.k) * h]);

    svg.attr("transform", t);
}
McGiogen

I'm facing the same problem today and I've done some tests.

I've noticed that it's the same weird behaviour happening when you have a translateExtent box smaller than the content's elements.

In your (and mine) code the same behaviour is triggered by zooming out: it doesn't matter if you have the translateExtent box correctly set with no zoom, if you zoom out the box is reduced at higher rate than the elements and at some point you will have translateExtent box smaller than the content (and the weird behaviour).

I temporary solved this as said here D3 pan+ zoom constraints

var MIN = {x: 0, y: -500},     //top-left corner
    MAX = {x: 2000, y: 500};   //bottom-right corner

function zoomed() {
   var transform = d3.event.transform;

   // limiting tranformation by MIN and MAX bounds
   transform.x = d3.max([transform.x, MIN.x]);
   transform.y = d3.max([transform.y, MIN.y]);
   transform.x = d3.min([transform.x, MAX.x]);
   transform.y = d3.min([transform.y, MAX.y]);

   container.attr("transform", transform);
}

I'm still a d3 newbie but I think that this is a bug in translateExtent code.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!