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...
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 + ")");
}
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 + ")");
}