D3.js Zooming and panning a collapsible tree diagram

不羁的心 提交于 2019-11-27 19:52:30

You can see (most of) a working implementation here: http://jsfiddle.net/nrabinowitz/fF4L4/2/

The key pieces here:

  • Call d3.behavior.zoom() on the svg element. This requires the svg element to have pointer-events: all set. You can also call this on a subelement, but I don't see a reason if you want the whole thing to pan and zoom, since you basically want the whole SVG area to respond to pan/zoom events.

    d3.select("svg")
        .call(d3.behavior.zoom()
          .scaleExtent([0.5, 5])
          .on("zoom", zoom));
    
  • Setting scaleExtent here gives you the ability to limit the zoom scale. You can set it to [1, 1] to disable zooming entirely, or set it programmatically to the max size of your content, if that's what you want (I wasn't sure exactly what was desired here).

  • The zoom function is similar to your dragmove function, but includes the scale factor and sets limits on the pan offset (as far as I can tell, d3 doesn't have any built-in panExtent support):

    function zoom() {
        var scale = d3.event.scale,
            translation = d3.event.translate,
            tbound = -h * scale,
            bbound = h * scale,
            lbound = (-w + m[1]) * scale,
            rbound = (w - m[3]) * scale;
        // limit translation to thresholds
        translation = [
            Math.max(Math.min(translation[0], rbound), lbound),
            Math.max(Math.min(translation[1], bbound), tbound)
        ];
        d3.select(".drawarea")
            .attr("transform", "translate(" + translation + ")" +
                  " scale(" + scale + ")");
    }
    

    (To be honest, I don't think I have the logic quite right here for the correct left and right thresholds - this doesn't seem to limit dragging properly when zoomed in. Left as an exercise for the reader :).)

  • To make things simpler here, it helps to have the g.drawarea element not have an initial transform - so I added another g element to the outer wrappers to set the margin offset:

    vis // snip
      .append("svg:g")
        .attr("class","drawarea")
      .append("svg:g")
        .attr("transform", "translate(" + m[3] + "," + m[0] + ")");
    

The rest of the changes here are just to make your code work better in JSFiddle. There are a few missing details here, but hopefully this is enough to get you started.

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