1

This is a continuation of my efforts to build a collapsible tree layout using d3.js.

Generate (multilevel) flare.json data format from flat json

The layout looks like: (http://bl.ocks.org/mbostock/raw/4339083/) with around 3k nodes and depth of some nodes around 25. The current size of the canvas I need to set is 8000px width and 8000px height in order that all nodes are visible which I know is not reasonable when the number of tree levels rendered is 2 or 3. Furthermore, I intend to make this code reusable with other trees that maybe smaller/larger in size based on what data source(json file) is selected.

So I was wondering if it is possible to resize the canvas size relative to the positions of the nodes/ number of nodes shown on screen. This way, the code would be much more systematic and adaptable.

I saw this:

Dynamically resize the d3 tree layout based on number of childnodes

but this resizes the tree, which if you can imagine in a case of tree with around 3k nodes, makes it hard to read and comprehend.

I know this might not even be related to d3.js but I tagged it to explain my issue and bring in d3 experts too who might have faced a similar condition.

I am also attempting to filter out uninformative nodes based on my criteria so as to render less number of nodes than the actual data. (I know i will run into performance issues with larger trees). Any help would be much appreciated.

NOTE: When I say canvas, I mean the area on which the tree is drawn and not the "canvas". I am not familiar with the jargon so kindly read accordingly.

Community
  • 1
  • 1
synaptikon
  • 699
  • 1
  • 8
  • 16
  • The thing is, the _nodes_ are appended to a _canvas_ that already exists... if it _exists_ it has a certain _size_. I think that for you to be able to do this, you would have to traverse the whole tree and calculate the number of levels in your structure and then resize the the SVG area accordingly... But, have you considered scrolling/panning the area to reveal the sections of interest? You can even zoom in/out to a certain area if needed. I solved my problems regarding large visualizations this way everytime... – Joum Aug 13 '13 at 08:48
  • If you want to have a look at it, this might help: http://stackoverflow.com/questions/17405638/d3-js-zooming-and-panning-a-collapsible-tree-diagram – Joum Aug 13 '13 at 08:50
  • First of all, Thank you for responding :). I looked at it and incorporated it in my code. Tried the zooming and panning example but since the tree is pretty big, it gets annoying. (You might wanna scroll to get to some node but instead it zooms out :( ).Also, it feels a bit glitchy (possibly due to large number of nodes in the tree). – synaptikon Aug 14 '13 at 17:56
  • Even so, zooming might help you... Consider calculating the _depth_ (ie, the number of levels) of your tree and then use that value to dynamically determine a scale factor for your zoom function. Then, apply zoom with that factor to the whole SVG area and that way you would rescale the whole graph to fit your _canvas_, whatever size it may be. Regarding the mouse-wheel zooming instead of scrolling, I think there is an option in the API to disable zoom on mousewheel, not sure though... – Joum Aug 16 '13 at 07:14
  • I just found this which seems to do the trick nicely http://stackoverflow.com/questions/13103748/dynamically-resize-the-d3-tree-layout-based-on-number-of-childnodes – Rob Schmuecker Nov 19 '13 at 06:53

2 Answers2

2

I was facing the similar problem and now I have find out a solution. Check on this link. D3 collapsible tree, node merging issue

Community
  • 1
  • 1
Manish Agrawal
  • 794
  • 1
  • 9
  • 23
2

Hope this helps someone.

I faced similar problems also using the flare tree code as a base for what I was building and the suggested links did not seem to account for a lot of variance in node structure? I have many trees to display with a dynamic number of nodes and structuring. This solution worked for me:

Concerning height: After observing the translate offsets per node, I learned that d.x (vs d.y, as tree is flipped) is an offset from the root node, with the nodes above root going negative and those below going positive. So, I "calculated" the max offset in both directions each time a node is appended, then with that information, adjusted the canvas height and the view translation (starting point of root).

For width: max d.depth * by the (y length normalization the code uses) + margins

let aboveBount = 0
let belowBound = 0
let maxDepth = 0


nodeEnter.each( (d) => {
  if( Math.sign(d.x) === -1 &&  d.x < boundAbove) {
    boundAbove = d.x
  } 
  if( Math.sign(d.x) === 1 &&  d.x > boundBelow) {
    boundBelow = d.x
  }
  
  if( d.depth > maxDepth){
    maxDepth = d.depth
  }

})

const newHeight = boundBelow + Math.abs(boundAbove) + nodeHeight*2 + margin.top*2


svg.style('height', newHeight)
svg.style('width'. maxDepth*180 + margin.left*2) 
//180 was the amount set to normailze path length

svg.attr('transform', `translate(${margin.left}, ${Math.abs(boundAbove) + margin.top})`)

Well, best wishes and happy coding!

Jackie
  • 76
  • 3