javascriptd3.jszoomingforce-layout

D3 selective Zoom


I am working on a force directed graph layout with some added features: selectable links/nodes, tooltips, fisheye effect, and -- important for my question -- zoom and pan.

Now, the zooming works very well like this:

d3 ... .append('svg:g').call(d3.behavior.zoom().on("zoom", redraw))... 

Where the redraw function looks like this...

function redraw() {
  trans = d3.event.translate;
  scale = d3.event.scale;
  vis.attr("transform", "translate(" + trans + ")" + " scale(" + scale + ")");
}

However, this method zooms the entire SVG graphic, including font sizes, graph edges, the line stroke-widths surrounding the nodes, etc.

Is it somehow possible not to zoom certain elements? The only solution I have seen so far is to put a line like this (took it from here http://jsfiddle.net/56RDx/2/)

node.attr("font-size", (nodeFontSize / d3.event.scale) + "px");

in the redraw method, to basically invert the zooming on certain elements on the fly. My problem is however (apart from this being an ugly hack), that my edge-widths are dynamically generated on graph-drawing (according to some graph properties...), so this 'invertion' method does not work...


Solution

    1. you can add a class to the element you want to trigger the zoom on:

      d3 ... .append('svg:g').classed("some_classname", true).call(d3.behavior.zoom().on("zoom", redraw))...
      

      then do:

      function redraw() {
        trans = d3.event.translate;
        scale = d3.event.scale;
        vis.selectAll("some_classname").attr("transform", "translate(" + trans + ")" + " scale(" + scale + ")");
      }
      

    2. or you can add a class to all elements you don't want to trigger the zoom on then use the CSS3 :not pseudo-class:

      function redraw() {
        trans = d3.event.translate;
        scale = d3.event.scale;
        vis.selectAll("*:not(.some_classname)").attr("transform", "translate(" + trans + ")" + " scale(" + scale + ")");
      }