jeroen.verhoest
jeroen.verhoest

Reputation: 5183

Dendrogram D3 show links on both sides

In the following example: http://bl.ocks.org/mbostock/4063570 you have a dendrogram where all the links all displayed on the right, is there a way to split this in half and show on part on the right and the other part on the left?

I was almost able to do it but it isn't correct: http://jsfiddle.net/8EM4s/3/. I thought by using 2 seperate diagonals to draw the left and the right links would work but the Y values are still calculated like there were directly underneath eachother:

var diagonalLeft = d3.svg.diagonal()
       .projection(function(d) { return [-d.y, d.x]; });

var diagonalRight = d3.svg.diagonal()
       .projection(function(d) { return [d.y, d.x]; });

Upvotes: 3

Views: 1471

Answers (1)

jeroen.verhoest
jeroen.verhoest

Reputation: 5183

You can find my solution here: http://jsfiddle.net/5TK3d/

        var numItems = Math.round(root.children.length /2);
        var nodePositionDictionary = {};
        var rootLeft = {children:[], name:root.name};
        var rootRight = {children:[], name:root.name};
        for(var i=0;i<root.children.length;i++)
        {
            var node = root.children[i];
            if(!(i < numItems))
            {
                rootRight.children.push($.extend({}, node));
            }else{
                rootLeft.children.push($.extend({}, node));
            }
        }       
        var nodesRight = cluster.nodes(rootRight);
        for (var i = 0; i < nodesRight.length; i++) {
            var node = nodesRight[i];
            node.right = true;
            nodePositionDictionary[node.name + (node.parent?node.parent.name:"")] = node;
        };
        var nodesLeft = cluster.nodes(rootLeft);
        for (var i = 0; i < nodesLeft.length; i++) {
            var node = nodesLeft[i];
            node.right = false;
            nodePositionDictionary[node.name + (node.parent?node.parent.name:"")] = node;
        };

        // manually create nodes with their positions instead of doing cluster.nodes because 
        // i want them to be drawn left and right
        var nodes = [];
        updateNodePositions(root);
        function updateNodePositions(n)
        {
            var nodePosition = nodePositionDictionary[n.name + (n.parent?n.parent.name:"")];

            if(nodePosition){
                n.x = nodePosition.x;
                n.y = nodePosition.y;
                n.depth = nodePosition.depth;
                nodes.push(n);
            }

            for(var i=0; i< n.children.length;i++)
            {
                var node = n.children[i];
                node.parent = n;

                nodes.push(node);

                var childNodePosition = nodePositionDictionary[node.name + (node.parent?node.parent.name:"")];
                if(childNodePosition){
                                    node.x = childNodePosition.x;
                                    node.y = childNodePosition.y;
                                    node.depth = childNodePosition.depth;
                                    node.right = childNodePosition.right;
                }

                if(node.children){
                    updateNodePositions(node);
                }
            }

        }

Upvotes: 4

Related Questions