D3 js Drag and Drop Zoomable Tree.

D3 js Drag and Drop Zoomable Tree.

D3 js Drag and Drop Zoomable Tree.

D3 js Drag and Drop Zoomable Tree. Zoomable, Panning, Collapsible Tree with Auto-sizing.

Below you can see an example of a D3.js Drag and Drop Zoomable Tree which is collapsible, panning and auto-sizing.

I recently had a need for this functionality for a project and was unable to find any previous examples of such on the internet.  Using the awesome D3.js library by Mike Bostock, I was able to get exactly what I needed with a bit of trial and error.  Here I open up my efforts for others to leverage.  It is certainly a visually pleasing and nifty tool.  You can theme it with CSS as you would anything else.

This example pulls together various examples of work with trees in D3.js.

The panning functionality can certainly be improved in my opinion and I would be thrilled to see better solutions contributed.

One can do all manner of housekeeping or server related calls on the drop event to manage a remote tree dataset for example.  However here I simply append any dropped node as a child to the node being dropped upon.

Dragging can be performed on any node other than root (flare). Dropping can be done on any node.

Panning can either be done by dragging an empty part of the SVG around or dragging a node towards an edge.

Zooming is performed by either double clicking on an empty part of the SVG or by scrolling the mouse-wheel. To Zoom out hold shift when double-clicking.

Expanding and collapsing of nodes is achieved by clicking on the desired node.

The tree auto-calculates its sizes both horizontally and vertically so it can adapt between many nodes being present in the view to very few whilst making the view manageable and pleasing on the eye.

The source code can be found here: https://gist.github.com/robschmuecker/7880033

And an example of it working with code in the same view is here:- http://bl.ocks.org/robschmuecker/7880033

The main source code excluding jQuery as a helper for getting element sizes (used only once) and the D3.js library can be found below as javascript:

Below is the CSS used in the example above

I hope it can help others looking for a similar tool.
R.

Edit 14/10/2015

A kind lady by the name of Irina Papuc contacted me from Toptal.com she found this article and suggested that I perhaps be so kind to let all my kind good readers know about their blog.  So in a show of good faith – here my dears is the Toptal Blog with another nice D3.js article http://www.toptal.com/javascript/a-map-to-perfection-using-d3-js-to-make-beautiful-web-maps Happy D3’ing. R.

139 thoughts on “D3 js Drag and Drop Zoomable Tree.

  1. jaydipsinh

    such a great work @@

    i was looking for the same and i redirect here. but i have to implement collapsible feature inside bounded force layout graph. i’ve tried so much but couldn’t integrate collapsible feature inside force directed graph. please help me or guide me how to do that.. also i posted this issue on stackoverflow .. have a look on this
    http://stackoverflow.com/questions/20857298/how-to-merge-collapsible-feature-in-bounded-force-directed-graph

    Thanks 🙂

  2. Paul Knittel

    Hey Rob,

    Amazing example you posted there. Your demo with 50,000 nodes is particular impressive.
    Is there a way to get the flare.json file back with the modified data from the drag and drop?

    Looking forward to your response. Thanks mate.
    Paul

      1. Jari

        I’m a newbie here but thanks for a truly fantastic demo especially the feature where you can modify the tree with drag’n’drop of nodes. I’m in a (non-profit) DNA-project where this could be very useful to visualize haplogroups in a tree, see example: http://www.viitasaari-dna.org/haplotree/isogg.html. The ultimate thing at this stage would be to get a modified tree back to the console as “sanitized ” JSON (as you describe above). I looked into and tried the other example referred to by Paul Knittel but it didn’t work for me with your original drag’n’drop tree. You don’t happen to have a working example of that?

        1. Jari

          I get the wanted output in the console by adding the call: console.log(JSON.stringify(root)) under Update; but it only works when the page is loaded. When I drag’n’drop the nodes I get the error: “Uncaught TypeError: Converting circular structure to JSON “. Any idea or simple solution?

  3. Bhavin

    Hi Rob,

    Thanks a lot for this demo, We are trying to update the graph very often, on click of a button, we are creating a JSON and displaying its required graph. But the code breaks on IE9. What happens is, when we click a button, we can see the graph being created initially, but if we click the button again to create another tree, we do not see any change reflected and the page appears blank. Essentially If I clear the cache and reload the page, the updated diagram appears, while this is not the case with Firefox and Chrome. Is it the D3.js Incompatibility or something in general with regards to JSON Parsing and Caching with regards to IE9.

  4. Shay

    HI,

    Do you know how add label to the edges of this tree ?

    I searched in Google and found some results from Stackoverflow, without any success?

  5. Sum

    Hi Rob
    The example you posted here is awesome.
    I want to read data from xml file or otherwise use a local javascript object to read the data.
    Can you suggest some simple way to achieve this?

  6. Tom

    Hi Rob
    I really love this project.
    I would like to ask you for advice of how to best add new nodes to the tree.

    Ideally I’d like a plus button somewhere which creates a free-standing node, then be able to drag this new node to someplace on the tree.
    Then on the drag end “action” I will send an ajax request to the server which makes it’s own updates to the underlying data model as you suggested in the comment response above.
    I am open to a different implementation, the essential point being that I need to be able to add new nodes to the tree which are unknown at the time of loading.

    Here is a simplified version of your example:
    http://codepen.io/anon/pen/Eclkm/

    Also, it would be great if we could set all of the nodes to be collapsed by default.

    Thanks in advance.

  7. ReddPool

    Hi,

    Awesome work ! Both of your exemples are amazing.

    I just had 2 questions :
    – Tell me if I’m wrong, but you had to code the hierarchy of your code, is there a way to obtain it from a database ? And is it possible to communicate with the database quickly enough to see the results when someone dropped a node ?
    – What are the node sizes ?

    Thanks. I’m really new to JS and even more to d3 but I’ll be really glad to understand it better.

  8. suraj

    Hi Rob,
    What I want to achieve is to draw a collapsable tree with data from mysql database .I have seen example
    where json file is use to get data , Please help me how to draw collapsable tree & we take data from database table

  9. suraj

    Thks for your reply Rob , but I’m not able to get it working .As you have mention in Reply to ReddPool on 17 april 2014 that in your previous projects you build the hierarchy directly from DB and echo it out as JSON for D3.js to use.I am trying to achieve the same from last 2 days but not able to do it.
    Can to plz help me with how to build the hierarchy directly from DB for collapsible tree and echo it out as JSON for D3.js and how to use it in D3.js .I have not done this before that why asking you all this things in details .Hope you understand.

    Thanks in advance .

  10. Suraj

    Hi Rob,
    I am using PHP and mysql .Database structure anything which is suitable for d3.js colapsible tree.Example Database Table. id(auto increment), name, parent . (or even u can change structure if u want to )
    I have to create var treeData array as in Fiddle ( http://jsfiddle.net/draut/nCttr/3/ ).
    I have to create this structure(dynamically) in php by calling values of Database.
    You can also provide help on stackoverflow
    http://stackoverflow.com/questions/23514763/convert-flat-json-to-tree-view-like-json/23515077? noredirect=1#comment36069211_23515077

    Any help is appreciable .Thanks…

  11. Arun K

    Really cool what you have done here!!! 🙂

    I am trying implement it locally without a server where the data is hard coded in the code itself. I am not able to achieve it, I am guessing, due to the usage of node.js . Is there a way to achieve the rendering of the tree without a server? Can the node.js references be substituted with equivalent ones?
    Thanking you in advance.

    Arun

      1. moses

        I tried it but I still get a blank page.. Here is my code:

        $(document).ready(function(){

        json = { here is my complete json.flare content

        };

        treeData = json;

        “your complete javascript code” without treeJSON = d3.json(“flare.json”, function(error, treeData) {…

        I got no error on the console.

        Here is my index.jade file:

        extends ../layouts/home
        head
        meta(http-equiv=’encoding’, content=’text/html’, charset=’UTF-8′)
        block content
        script(type=’text/javascript’ src=’js/d3.min.js’)
        script(type=’text/javascript’ src=’http://code.jquery.com/jquery-1.10.2.min.js’)
        script(type=’text/javascript’ src=’js/dndTree.js’)
        link(rel=’stylesheet’, href=’stylesheets/tree.css’)

  12. Perok

    could you please give us a hint on how one could show in abeautiful and clear way the size of each node in the diagram? Seems all this info now is not shown, right? For example we could increase the circle’s node size? or use a color climax? (cold colors small values. warm colors higher values?)

    thank you

  13. Roberto Aragón

    Hi, Rob:

    First of all, I would like to thank you for your example.
    Next, a question: what is your code licence?

    Regards,
    Roberto.

  14. Gehiks

    Hi Rob,

    This work is really awesome. As I’m trying to implement it I’d like to know how to disable the zoom on mouse wheel. How can I do it?

    Regards,

    Gehiks

  15. Guillaume

    Hi Rob,

    Your work is really good !
    It is perfect to represent the organization of the society in which I work.
    I just have a little question: is it possible to obtain a vertical tree ?
    It would be really great!
    Thank you in advance.

    Regards,

    Guillaume.

      1. Raja

        Hi,

        I want to do something similar to the tree diagram above. However my problem is that I have a child node which takes relationship from two parental nodes.

        For example: A-> B, C-> D and B&D -> E (Both B and D have a common child D) How can I fix this.

        Thank you very much for helping me out.

        Br,
        Raja

          1. Raja

            Hi

            Can you point any sources, how to have multiple json files for one visualization in d3?

            Thank you,

            Br,
            Raja

          2. suresh

            Hi Rob,
            Thanx for the quick reply.. can you give a working example for the same
            As per the previous comments i understood that
            First i should draw the tree without cross connections
            then i should have seperate json file which will have cross connections
            am i correct in understanding it … if so how should be my second json file look like… i saw your couplings example in github but can i have a working example for the same
            if my understanding is wrong can you explain in detail. Thank you very much

  16. Tapan Bohra

    Hi rob,
    I saw this on D3s main website in example section and found this very useful but I have an issue.
    Every time the tree is loaded , it shows the entire tree which if is huge covers the entire page and it becomes difficult to than close each node one by one, I want to manually open nodes and edges which I want.
    Can you suggest what changes I have to make in the code??

  17. Jessie

    Hi, thanks for this great example!
    I’m using your code as a reference for something I’m building. I was wondering though — when you drag, you remove the children nodes and links. However if that node wasn’t originally collapsed, it would expand again when it’s connected to another node. Where in your code does that happen? My code so far would remove the children nodes and links but then after I drop the node, it stays collapsed.

    Also, would it possible to drag a node somewhere and then having the node stay at the dropped spot and the links extended to the node?

    Thanks again.

  18. Tom Bortels

    Rob – this is stunningly good. I just wanted to say I appreciate you posting the demo and code and explanation tremendously – I learn best from good working examples, and that is this. The people like yourself who take the time and effort to share are my personal heroes. Just wanted to say thank you – so, Thank you!

  19. Virginia

    Hi Rob,

    Like everybody else, I’m super thankful that you posted this online. I couldn’t have found something more fitting for what I want to do than this.

    I was wondering if it would be possible to replace the diagonal with a polyline, or a line with multiple points. Basically, I am going for less of a curvy link between nodes, and more of an angled off, straight-edged kind of link. Does that make sense? If you have an idea of how you’d approach this, I’d love to hear it, thanks so much again!

  20. Mélanie

    Hi Rob,

    Thanks for this example, the code, the tuto. That’s great especially for a beginner! I like the tree representation and I used it for our current project. The idea is to map legal and institutional frameworks and it works well. This is my first D3 visualization and I like it. I have two questions though: how can I change the size of the link between nodes? And the second one is: would it be possible to add a search function?
    Thanks.
    Mélanie

  21. Vlad

    Very nice work!

    Is it possible to load the json at on click event based on node ? (aka lazy loading?)
    in other words, intercept the click event, display some data, update the child nodes (server side json with only 1 level children) and then collapse the branch ?
    Vlad

  22. mutongwu

    Hi Rob,
    What I want to achieve is to diff the ghostCircle where mouseover event happened. for example,make the ghostCircle have a green color which indicates that it might be a proper “drop” action.

    Is it possible ? thanks.

      1. mutongwu

        just the one being hovered on which the tempConnector line is connected to. ———–yes ,this’s what i want.
        —————————–
        and i have another question: is there a good way to avoid overlapping of nodes ? when i change the size of each circle (no more the default 4.5 , but between 5 to 15 randomly), nodes overlapped. So i change the code in function “update” as following :
        var newHeight = d3.max(levelWidth) * 35 ; // default 25 pixels per line

        is there a better advise ? 🙂

  23. pradeep kumar

    You are amazing..! You stop by everyone’s question and answered everyone..! Hats off bro.! I appreciate it..! Thanks for the help you did to all..! 🙂

  24. quique

    Hi Rob,

    First of all, congrats for the superb work and support.

    I was wondering about mobile browsers behaviour of the drag&drop functionality. I have tested it on chrome browser in both samsung tablet, mobiles and other android devices and it seems to be a very elusive thing to do for the user and sometimes it simply does not work.

    Is this something to do with D3js and mobile browsers (I am new to D3js) or is there any workaround / fix to achieve drag&drop in mobile devices?

    Thanks in advance,
    quique

  25. beckham

    Dear Rob Schmuecker!
    Thanks for your posts. I have a question: in case of thousand of nodes, query and build json data are not good for perfomance. How to lazy load the children when the parent node clicked?

  26. beckham

    Hi Rob!
    I’m modifying your code, i need to custom the tree, tree with text, image inside the rectangular nodes and direction is top-bottom.
    I have tried to modify some codes, but running not fine. Could you help me out?
    Thanks a lot!

  27. Max

    Hi,
    A very good piece of work.Is there anyway through which I can get a list of all nodes in your tree? tree.nodes(root) function returns only those nodes which are not the descendants of a collapsed node, however what I require is a list of all nodes irrespective of whether any of there ancestor is collapsed or not…

  28. myra

    Hi Rob,

    I want to change the color and the width of the link dynamic based on the no of visits to the path and the useful status. For example if my paths a->b->c->d has 3000 visits and useful 1, whereas a->b->e-f has 200 visits and useful 0, where should i make the change in the code to reflect the effect whenever a node is selected

  29. mojtaba

    Hi

    thanks for your post, I’d like to say that I am going to save the changes when I drag and drop some tree items and I’d like to edit the layout by using drag and drop option and then save new layout, can you please tell me how I can do that ?

    thanks.

      1. mojtaba

        Thank you so much for the response.

        I have another question. I’d like all the nodes to be closed when I click on the root node.

        for example I have a root node with 10 children and each child has 5 children. assume that all children are open and when I click on the root and then reopen it, I want all 5 children of to be closed and only the first level 10 children be shown. How can I do that ?

        thanks in advance.

  30. Rashed Hoque

    Hello Rob,

    Awesome, fantastic … great stuff. Thanks for sharing. You answered so many comments… great attitude. Not sure if you are still following/answering the comments, if so would mind to have a look into few things I would like to tweak. (Sorry I am pretty much beginner in d3)

    1. To put hyper-links ( <a href..) on each node text, which part of your code needs to be updated?
    2. For long text (to set as text or hyper-link text) how to wrap or make fit in multiple lines?

    Finally, not really d3 stuff, more of creating the hierarchical data structure. I am using a function that returns the following when I pass id 1234:

    { id: "1234", value : 34, children : [ { id: "3456", value: 56} , { id: "9870", value: 43} ] }

    now I need some kind of recursion so that when I pass the "id" of "children" it returns "children" and then the json gets updated. As an example if I pass id "3456":

    First it returns : { id: "3456", value: 56, children : [ { id : "8899", value : 45} ] }
    And then the root document gets updated like:

    { id: "1234", value : 34, children : [ { id: "3456", value: 56, children : [ { id : "8899", value : 45} ] } , { id: "9870", value: 43} ] } ..note how the root json gets updated with children of "3456". So this is basically recursively getting "children" and updating the original json document, am trying to solve it in ruby.

    Any help would be greatly appreciated! By the way, just curious to know, have you any interest in freelancing work?

    Thanks,
    Rashed

      1. Rashed Hoque

        Hello Rob,

        Thanks a lot for your reply. Yeah it’s something to be done in server side. I really appreciate your idea, will try and get back to you.

        Am trying to tweak your d3 code to :

        1. Include hyper-links on node text
        2. Wrap long text fit in either multiple lines

        Any guide line how to achieve the above mentioned features? Do I need to use something called “foreign object”? Grateful if you could comment.

        Good to know your interest. Will get back to you soon!

        Cheers,
        -Rashed

  31. Davor Gobac

    Hi Rob,
    Amazing work. Thank you very much.

    I havent started to change your code to my needs just yet, beacuse of business rules I need to imnplement.

    I need a tree that spreads left and right of the root node. Something like your example with a mirror in the middle :). Can it be done? If it can than this is a solution that I can start to implement.
    I have seen the radial solution: http://jsfiddle.net/Nivaldo/CbGh2/, but it is not good for me because the nodes run wild when expanded. I want them to behave like they do in your example. I have a hunch that if I want to implement this i’ll need to change the D3.js file?

    Once again, thank you for all the hard work you have done.

    1. Davor Gobac

      Hi,

      Found the solution on : http://bl.ocks.org/jdarling/2073ba4c2d640236e2e2.
      Now all I need to do is apply it on your tree view becuase of look and feel.
      I made some changes to the layout of the nodes, because I want particular nodes left and right.
      I added level attribute to JSON top nodes and depending on that showing them left or right instead of a mod keyword.
      for (; i < l; i++) {
      if (json.children[i]["level"] == "0") {
      json.left.push(json.children[i]);
      json.children[i].position = 'left';
      } else {
      json.right.push(json.children[i]);
      json.children[i].position = 'right';
      }
      }

      D.G.

  32. Jari

    Hi again! I use “centerNode((root),zoomListener.scale(0.25));” to set the zoom level depending of the extent of branches in different haplotrees we have, refer to: http://www.viitasaari-dna.org/haplotree/

    But how to zoom into an arbitrary node? I tried to to use the id or the name instead of the ‘root’ above but I can’t get it to work!

    I haven’t seen you around in Halmstad yet!! The food and drinks are still here! 😉

    Bes regards
    Jari

  33. Amit

    Hi Rob,

    That’s an awesome visualization of d3 you have made. I want to take this one step ahead i.e. I want to display a tool-tip containing the data of the nodes on mouseover.

    Please help me with that?

    Thanks in advance.

      1. Flavia

        Hello Rob,
        thank you for sharing your implementation of tree view. It already helped me a lot.
        Also thank you Jari for opening and sharing your example of tooltip. I also need to have the tooltip implemented in the tree view.
        I copied the functions mouseover(d) and mouseout(d) from your example to Rob tree view code. But it is still not showing the tooltip when mouseover the node. Do you have any tips where should I add them and if there is anything else I should do?

        Thanks for any help.
        Flavia

  34. rasha

    hi…
    i would like to thank u very mush
    but i have two question
    1-how to change circle size??
    2-how change the point(x,y)to root node??
    thank u very very very very much…..

      1. rasha

        hi how are u
        i would like to ask question
        can we do son nodes appear in circle ship around father node like sun brights with all the features of this model or it is impossible???
        please help me ….. i am waiting u

  35. John

    Hi, I sent you an email about a question I have. Also,following is my second question:

    in “flare.json” what does:
    “”size”: 3938″ means or does.

    I changed its value but nothing seems to happen visually.

    Thanks

  36. Garima

    Hi,

    I have a structure where a node is child to more than one parent. Example: A->B; A->C->B. But this is not working in this case. Can it be handled?

  37. Randy

    Hey there Rob! I’ve been working on an implementation of this treeview using json that is sent by a server and then consumed by us. It’s pretty much up and running at this point but I’m still having trouble when I click to hide a node’s child nodes. All of my nodes and links get bundled up in that one node I have clicked. Any idea what might be happening in this case? Really great stuff by the way and thank you beforehand with any help you can provide me with!

  38. Laurent

    This is tremendous work Rob I have to admit! There’s one lingering question I have after going through your code and the different comments on this thread: do you think there would be a way to reverse the tree to JSON after you’ve modified it? For my purposes, I see value in being able to output the newly-modified tree to JSON and comparing it to the original input. Do you have any insight on that?

  39. Mike

    Hi Rob!
    The nodes order in my json data is A-B-C-D-E, but when show on the tree, the order did not like that, it becomes E-C-D-A-B, how can i fix it? Thank you!

  40. Flavio Jarabeck

    Astounding code and example! Congratulations!

    One question: How can I structure the JSON code to differentiate between nodes that are categories and nodes that point to a webpage (the end of the tree would be links to web pages), so I can style them properly… I’m trying with no success…

    thanks in advance!

    🙂

      1. Flavio Jarabeck

        Hi Rob, Thanks for the information… reading other posts in this page I found a way to do that… done!

        Thanks again!

Leave a Reply

Your email address will not be published. Required fields are marked *