1

I builded a tree after this example. Now that I have some data the inital zoom is too close, so I want to set the initial zoom level that my data fits the screen. I would be totally fine with a manual approach where I set the scale in the script. Of course it would be also very nice to make it dynamically, depending (only) on the width (so that all horizontal data is shown).

This is the zoom function in the script:

function zoom() {
    svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}

And this is the zoomlistener function:

var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom);

I've already read some articles here and there (and some others), but I don't understand how to implement those solutions into my tree as I'm pretty green with d3 and programming in general.

Thanks in advance for your help! :)

Maki
  • 109
  • 13

1 Answers1

5

Finally I found a solution by myself with some more articles. The main code snippets that helped (after reading a lot more things) were given by this article which was not sufficient explained for me in first instance.

So, the solution with the given example tree code is the following:

To set the initial zoom level you need to add one line to the g-element that is for the zoomlistener to work (it is pretty much on the bottom of the script) that it looks like:

// Append a group which holds all nodes and which the zoom Listener can act upon.
var svgGroup = baseSvg.append("g")
    .attr("transform","translate(100,30)scale(.3,.3)");

I basically just add an attribute to the g-element that holds all other nodes. In this attribute is the initial zoom level set. It seems important that the translate values and the scale are the same (30/100 = 0.3 ;) ). Otherwise it doesn't work propely.

But now is the problem, that when we want to zoom or move accross the tree for the first time it jumps back to scale 1 which is not that nice for the user as he will be confused by this sudden jump.

To have a smooth user experience, I added only a small line to the above mentioned zoomlistener that it looks like this (its the same translate and scale as before):

 var zoomListener = d3.behavior.zoom().translate([100,30]).scale(.3).scaleExtent([0.3, 3]).on("zoom", zoom);

Now the initial zoom level is hardcoded and easily adjustable - and the best of all: it only took two lines :D

I will try a dynamic approach. When I have a solution I'll edit this solution :)

EDIT: I found a dynamic solution - at least for my case: When the data of my tree is created (customizable) with php, I check the depth of the tree (how many nodes are in one row). This depth is written into the SESSION. Before the start of my tree-function in my javascript I initialize and set:

var depth_of_tree = window.SESSION.depth_of_tree;

And the initital scale with 1 divided by the ln of the depth:

var initscale = 1 / Math.log(depth_of_tree); 

Then, I change the zoomlistener with the following lines:

//var initscale = .3;
var inittransx = 100;
var inittransy = inittransx*initscale;

// define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents
var zoomListener = d3.behavior.zoom().translate([inittransx,inittransy]).scale(initscale).scaleExtent([0.3, 2]).on("zoom", zoom);

and:

// Append a group which holds all nodes and which the zoom Listener can act upon.
var svgGroup = baseSvg.append("g")
    .attr("transform","translate("+inittransx+","+inittransy+")scale("+initscale+","+initscale+")");

This results in pretty nice scales no matter how deep the tree is. (you may have to play a bit with the numbers)

Maki
  • 109
  • 13