markdown 拖放,可折叠d3.js具有50,000个节点的树

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown 拖放,可折叠d3.js具有50,000个节点的树相关的知识,希望对你有一定的参考价值。

{
    "user_id": 0,
    "name": "Root Node",
    "children": [
        {
            "user_id": 0,
            "name": "Flossie Hickman",
            "children": [
                {
                    "user_id": 0,
                    "name": "Violet Arnold",
                    "children": [
                        {
                            "user_id": 0,
                            "name": "Buckner Carrillo",
                            "children": [
                                {
                                    "user_id": 0,
                                    "name": "Scott Poole"
                                },
                                {
                                    "user_id": 1,
                                    "name": "Travis Compton"
                                },
                                {
                                    "user_id": 2,
                                    "name": "Brenda Galloway"
                                },
                                {
                                    "user_id": 3,
                                    "name": "Paula Dennis"
                                },
                                {
                                    "user_id": 4,
                                    "name": "Deleon Golden"
                                },
                                {
                                    "user_id": 5,
                                    "name": "Russell Mcknight"
                                },
                                {
                                    "user_id": 6,
                                    "name": "Fischer Serrano"
                                },
                                {
                                    "user_id": 7,
                                    "name": "Cochran Hart"
                                },
                                {
                                    "user_id": 8,
                                    "name": "Martin Rollins"
                                },
                                {
                                    "user_id": 9,
                                    "name": "Karin Lara"
                                },
                                {
                                    "user_id": 10,
                                    "name": "Nannie Blanchard"
                                },
                                {
                                    "user_id": 11,
                                    "name": "Sharron Stark"
                                },
                                {
                                    "user_id": 12,
                                    "name": "Mcgowan Holcomb"
                                },
                                {
                                    "user_id": 13,
                                    "name": "Snider Barrett"
                                },
                                {
                                    "user_id": 14,
                                    "name": "Janice Atkins"
                                }
                            ]
                        },
                        {
                            "user_id": 1,
                            "name": "Payne Mack",
                            "children": [
                                {
                                    "user_id": 0,
                                    "name": "Barker Patrick"
                                },
                                {
                                    "user_id": 1,
                                    "name": "Guerrero Mathews"
                                },
                                {
                                    "user_id": 2,
                                    "name": "Gaines Greer"
                                },
                                {
                                    "user_id": 3,
                                    "name": "Estelle Morgan"
                                },
                                {
                                    "user_id": 4,
                                    "name": "Pollard Barnes"
                                },
                                {
                                    "user_id": 5,
                                    "name": "Alison Shepard"
                                },
                                {
                                    "user_id": 6,
                                    "name": "Imogene Hernandez"
                                },
                                {
                                    "user_id": 7,
                                    "name": "Rosalinda Morrow"
                                },
                                {
                                    "user_id": 8,
                                    "name": "Baxter Robbins"
                                },
                                {
                                    "user_id": 9,
                                    "name": "Mercado Stevens"
                                },
                                {
                                    "user_id": 10,
                                    "name": "Price Valentine"
                                },
                                {
                                    "user_id": 11,
                                    "name": "Mara Richards"
                                },
                                {
                                    "user_id": 12,
                                    "name": "Tommie Mcgee"
                                },
                                {
                                    "user_id": 13,
                                    "name": "Shepherd Pacheco"
                                },
                                {
                                    "user_id": 14,
                                    "name": "Gibson Preston"
                                }
                            ]
                        },
                        {
                            "user_id": 2,
                            "name": "Cox Slater",
                            "children": [
                                {
                                    "user_id": 0,
                                    "name": "Celia Jensen"
                                },
                                {
                                    "user_id": 1,
                                    "name": "Myers Warner"
                                },
                                {
                                    "user_id": 2,
                                    "name": "Kane Burns"
                                },
                                {
                                    "user_id": 3,
                                    "name": "Karyn Gonzalez"
                                },
                                {
                                    "user_id": 4,
                                    "name": "Winnie Perez"
                                },
                                {
                                    "user_id": 5,
                                    "name": "Finley Cook"
                                },
                                {
                                    "user_id": 6,
                                    "name": "Elizabeth Garrison"
                                },
                                {
                                    "user_id": 7,
                                    "name": "Daniel Simmons"
                                },
                                {
                                    "user_id": 8,
                                    "name": "Jan Luna"
                                },
                                {
                                    "user_id": 9,
                                    "name": "Leonor Sears"
                                },
                                {
                                    "user_id": 10,
                                    "name": "Marquita Santana"
                                },
                                {
                                    "user_id": 11,
                                    "name": "Boyer Hanson"
                                },
                                {
                                    "user_id": 12,
                                    "name": "Brock Hyde"
                                },
                                {
                                    "user_id": 13,
                                    "name": "Candice Jefferson"
                                },
                                {
                                    "user_id": 14,
                                    "name": "Odonnell Vargas"
                                }
                            ]
                        },
                        {
                            "user_id": 3,
                            "name": "Jodi Duran",
                            "children": [
                                {
                                    "user_id": 0,
                                    "name": "Carey Quinn"
                                },
                                {
                                    "user_id": 1,
                                    "name": "Lilia Vega"
                                },
                                {
                                    "user_id": 2,
                                    "name": "Marci Parker"
                                },
                                {
                                    "user_id": 3,
                                    "name": "Marguerite Bartlett"
                                },
                                {
                                    "user_id": 4,
                                    "name": "Jill Cooper"
                                },
                                {
                                    "user_id": 5,
                                    "name": "Bettie Curry"
                                },
                                {
                                    "user_id": 6,
                                    "name": "Owens Shannon"
                                },
                                {
                                    "user_id": 7,
                                    "name": "Lakeisha Rasmussen"
                                },
                                {
                                    "user_id": 8,
                                    "name": "House Glover"
                                },
                                {
                                    "user_id": 9,
                                    "name": "Forbes Short"
                                },
                                {
                                    "user_id": 10,
                                    "name": "Francis Finley"
                                },
                                {
                                    "user_id": 11,
                                    "name": "Darcy Singleton"
                                },
                                {
                                    "user_id": 12,
                                    "name": "Terry Villarreal"
                                },
                                {
                                    "user_id": 13,
                                    "name": "Graciela Wooten"
                                },
                                {
                                    "user_id": 14,
                                    "name": "Malone Dunlap"
                                }
                            ]
                        },
                      
                        {
                            "user_id": 4,
                            "name": "Sabrina Harrell",
                            "children": [
                                {
                                    "user_id": 0,
                                    "name": "Dalton Norman"
                                },
                                {
                                    "user_id": 1,
                                    "name": "Barrett Morales"
                                },
                                {
                                    "user_id": 2,
                                    "name": "Daniels Booth"
                                },
                                {
                                    "user_id": 3,
                                    "name": "Maxwell Rich"
                                },
                                {
                                    "user_id": 4,
                                    "name": "Bennett Washington"
                                },
                                {
                                    "user_id": 5,
                                    "name": "Lelia Banks"
                                },
                                {
                                    "user_id": 6,
                                    "name": "Georgette Joyce"
                                },
                                {
                                    "user_id": 7,
                                    "name": "Kaitlin Irwin"
                                },
                                {
                                    "user_id": 8,
                                    "name": "Lacey Case"
                                },
                                {
                                    "user_id": 9,
                                    "name": "Reyes Jenkins"
                                },
                                {
                                    "user_id": 10,
                                    "name": "Rios Dunn"
                                },
                                {
                                    "user_id": 11,
                                    "name": "Walsh Robles"
                                },
                                {
                                    "user_id": 12,
                                    "name": "Nieves Ratliff"
                                },
                                {
                                    "user_id": 13,
                                    "name": "Alta Brennan"
                                },
                                {
                                    "user_id": 14,
                                    "name": "Theresa Gilliam"
                                }
                            ]
                        },
                        {
                            "user_id": 5,
                            "name": "Woods Howe",
                            "children": [
                                {
                                    "user_id": 0,
                                    "name": "Adkins Mcguire"
                                },
                                {
                                    "user_id": 1,
                                    "name": "Blake Watts"
                                },
                                {
                                    "user_id": 2,
                                    "name": "Renee Floyd"
                                },
                                {
                                    "user_id": 3,
                                    "name": "Decker Riggs"
                                },
                                {
                                    "user_id": 4,
                                    "name": "Chen Benton"
                                },
                                {
                                    "user_id": 5,
                                    "name": "English Russo"
                                },
                                {
                                    "user_id": 6,
                                    "name": "Wood Cohen"
                                },
                                {
                                    "user_id": 7,
                                    "name": "Aisha Molina"
                                },
                                {
                                    "user_id": 8,
                                    "name": "Vargas Hensley"
                                },
                                {
                                    "user_id": 9,
                                    "name": "Rowena Ray"
                                },
                                {
                                    "user_id": 10,
                                    "name": "Clay Farmer"
                                },
                                {
                                    "user_id": 11,
                                    "name": "Kathryn Langley"
                                },
                                {
                                    "user_id": 12,
                                    "name": "Claudia Dominguez"
                                },
                                {
                                    "user_id": 13,
                                    "name": "Jeanne White"
                                },
                                {
                                    "user_id": 14,
                                    "name": "Mcleod Holden"
                                }
                            ]
                        },
                        {
                            "user_id": 6,
                            "name": "Holmes Wiley",
                            "children": [
                                {
                                    "user_id": 0,
                                    "name": "Leach Jacobs"
                                },
                                {
                                    "user_id": 1,
                                    "name": "Harriett Macdonald"
                                },
                                {
                                    "user_id": 2,
                                    "name": "Castro Bridges"
                                },
                                {
                                    "user_id": 3,
                                    "name": "Barber Stephens"
                                },
                                {
                                    "user_id": 4,
                                    "name": "Burnett Mills"
                                },
                                {
                                    "user_id": 5,
                                    "name": "Freida Jacobson"
                                },
                                {
                                    "user_id": 6,
                                    "name": "Juliana Norton"
                                },
                                {
                                    "user_id": 7,
                                    "name": "Lindsey Peck"
                                },
                                {
                                    "user_id": 8,
                                    "name": "Fran Spence"
                                },
                                {
                                    "user_id": 9,
                                    "name": "Sargent Hendrix"
                                },
                                {
                                    "user_id": 10,
                                    "name": "Marian Bates"
                                },
                                {
                                    "user_id": 11,
                                    "name": "Moses Buck"
                                },
                                {
                                    "user_id": 12,
                                    "name": "Fisher Whitley"
                                },
                                {
                                    "user_id": 13,
                                    "name": "Tammie Salas"
                                },
                                {
                                    "user_id": 14,
                                    "name": "Ratliff Wallace"
                                }
                            ]
                        },
                        {
                            "user_id": 7,
                            "name": "Mallory Terry",
                            "children": [
                                {
                                    "user_id": 0,
                                    "name": "Rena Levine"
                                },
                                {
                                    "user_id": 1,
                                    "name": "Karen Leonard"
                                },
                                {
                                    "user_id": 2,
                                    "name": "Reese Copeland"
                                },
                                {
                                    "user_id": 3,
                                    "name": "Rosemarie Mays"
                                },
                                {
                                    "user_id": 4,
                                    "name": "Lydia Cole"
                                },
                                {
                                    "user_id": 5,
                                    "name": "Estella Hood"
                                },
                                {
                                    "user_id": 6,
                                    "name": "Felicia Bradford"
                                },
                                {
                                    "user_id": 7,
                                    "name": "Suzanne Strong"
                                },
                                {
                                    "user_id": 8,
                                    "name": "Hannah Parks"
                                },
                                {
                                    "user_id": 9,
                                    "name": "Melendez Cruz"
                                },
                                {
                                    "user_id": 10,
                                    "name": "Snow Stout"
                                },
                                {
                                    "user_id": 11,
                                    "name": "Lillie Guzman"
                                },
                                {
                                    "user_id": 12,
                                    "name": "Patrica Dotson"
                                },
                                {
                                    "user_id": 13,
                                    "name": "Zimmerman Fields"
                                },
                                {
                                    "user_id": 14,
                                    "name": "Ruth Wong"
                                }
                            ]
                        },
                        {
                            "user_id": 8,
                            "name": "Eileen Jennings",
                            "children": [
                                {
                                    "user_id": 0,
                                    "name": "Alford Kelley"
                                },
                                {
                                    "user_id": 1,
                                    "name": "Jaime Drake"
                                },
                                {
                                    "user_id": 2,
                                    "name": "Fuentes Frazier"
                                },
                                {
                                    "user_id": 3,
                                    "name": "Combs Oliver"
                                },
                                {
                                    "user_id": 4,
                                    "name": "Dixie Davenport"
                                },
                                {
                                    "user_id": 5,
                                    "name": "Bishop Montgomery"
                                },
                                {
                                    "user_id": 6,
                                    "name": "Elisa Rogers"
                                },
                                {
                                    "user_id": 7,
                                    "name": "Dillard Gates"
                                },
                                {
                                    "user_id": 8,
                                    "name": "Amalia Livingston"
                                },
                                {
                                    "user_id": 9,
                                    "name": "Marva Small"
                                },
                                {
                                    "user_id": 10,
                                    "name": "Jones Frank"
                                },
                                {
                                    "user_id": 11,
                                    "name": "Gonzalez Moss"
                                },
                                {
                                    "user_id": 12,
                                    "name": "Albert Rutledge"
                                },
                                {
                                    "user_id": 13,
                                    "name": "Janell Burks"
                                },
                                {
                                    "user_id": 14,
                                    "name": "Coleen Saunders"
                                }
                            ]
                        },
                        {
                            "user_id": 9,
                            "name": "Alana Shepherd",
                            "children": [
                                {
                                    "user_id": 0,
                                    "name": "Compton Newman"
                                },
                                {
                                    "user_id": 1,
                                    "name": "Chase Shaw"
                                },
                                {
                                    "user_id": 2,
                                    "name": "Nancy Ryan"
                                },
                                {
                                    "user_id": 3,
                                    "name": "Terra Sawyer"
                                },
                                {
                                    "user_id": 4,
                                    "name": "Lang Landry"
                                },
                                {
                                    "user_id": 5,
                                    "name": "Cindy Haynes"
                                },
                                {
                                    "user_id": 6,
                                    "name": "Elisabeth Mercer"
                                },
                                {
                                    "user_id": 7,
                                    "name": "Deirdre Moody"
                                },
                                {
                                    "user_id": 8,
                                    "name": "Juliette Houston"
                                },
                                {
                                    "user_id": 9,
                                    "name": "Hopkins Knapp"
                                },
                                {
                                    "user_id": 10,
                                    "name": "Keith Charles"
                                },
                                {
                                    "user_id": 11,
                                    "name": "Rosario Hooper"
                                },
                                {
                                    "user_id": 12,
                                    "name": "Hooper Martin"
                                },
                                {
                                    "user_id": 13,
                                    "name": "Sullivan Harrington"
                                },
                                {
                                    "user_id": 14,
                                    "name": "Melba Lawson"
                                }
                            ]
                        },
                    ]
                }
            ]
        }
    ]   
}       
 
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
  
	.node {
    cursor: pointer;
  }

  .overlay{
      background-color:#EEE;
  }
   
  .node circle {
    fill: #fff;
    stroke: steelblue;
    stroke-width: 1.5px;
  }
   
  .node text {
    font-size:10px; 
    font-family:sans-serif;
  }
   
  .link {
    fill: none;
    stroke: #ccc;
    stroke-width: 1.5px;
  }

  .templink {
    fill: none;
    stroke: red;
    stroke-width: 3px;
  }

  .ghostCircle.show{
      display:block;
  }

  .ghostCircle, .activeDrag .ghostCircle{
       display: none;
  }

</style>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="dndTree.js"></script>
<body>
    <div id="tree-container"></div>
</body>
</html>
// Get JSON data
treeJSON = d3.json("manyNodes.json", function(error, treeData) {

    // Calculate total nodes, max label length
    var totalNodes = 0;
    var maxLabelLength = 0;
    // variables for drag/drop
    var selectedNode = null;
    var draggingNode = null;
    // panning variables
    var panSpeed = 200;
    var panBoundary = 20; // Within 20px from edges will pan when dragging.
    // Misc. variables
    var i = 0;
    var duration = 750;
    var root;

    // size of the diagram
    var viewerWidth = $(document).width();
    var viewerHeight = $(document).height();

    var tree = d3.layout.tree()
        .size([viewerHeight, viewerWidth]);

    // define a d3 diagonal projection for use by the node paths later on.
    var diagonal = d3.svg.diagonal()
        .projection(function(d) {
            return [d.y, d.x];
        });

    // A recursive helper function for performing some setup by walking through all nodes

    function visit(parent, visitFn, childrenFn) {
        if (!parent) return;

        visitFn(parent);

        var children = childrenFn(parent);
        if (children) {
            var count = children.length;
            for (var i = 0; i < count; i++) {
                visit(children[i], visitFn, childrenFn);
            }
        }
    }

    // Call visit function to establish maxLabelLength
    visit(treeData, function(d) {
        totalNodes++;
        maxLabelLength = Math.max(d.name.length, maxLabelLength);

    }, function(d) {
        return d.children && d.children.length > 0 ? d.children : null;
    });


    // sort the tree according to the node names

    function sortTree() {
        tree.sort(function(a, b) {
            return b.name.toLowerCase() < a.name.toLowerCase() ? 1 : -1;
        });
    }
    // Sort the tree initially incase the JSON isn't in a sorted order.
    sortTree();

    // TODO: Pan function, can be better implemented.

    function pan(domNode, direction) {
        var speed = panSpeed;
        if (panTimer) {
            clearTimeout(panTimer);
            translateCoords = d3.transform(svgGroup.attr("transform"));
            if (direction == 'left' || direction == 'right') {
                translateX = direction == 'left' ? translateCoords.translate[0] + speed : translateCoords.translate[0] - speed;
                translateY = translateCoords.translate[1];
            } else if (direction == 'up' || direction == 'down') {
                translateX = translateCoords.translate[0];
                translateY = direction == 'up' ? translateCoords.translate[1] + speed : translateCoords.translate[1] - speed;
            }
            scaleX = translateCoords.scale[0];
            scaleY = translateCoords.scale[1];
            scale = zoomListener.scale();
            svgGroup.transition().attr("transform", "translate(" + translateX + "," + translateY + ")scale(" + scale + ")");
            d3.select(domNode).select('g.node').attr("transform", "translate(" + translateX + "," + translateY + ")");
            zoomListener.scale(zoomListener.scale());
            zoomListener.translate([translateX, translateY]);
            panTimer = setTimeout(function() {
                pan(domNode, speed, direction);
            }, 50);
        }
    }

    // Define the zoom function for the zoomable tree

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


    // define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents
    var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom);

    function initiateDrag(d, domNode) {
        draggingNode = d;
        d3.select(domNode).select('.ghostCircle').attr('pointer-events', 'none');
        d3.selectAll('.ghostCircle').attr('class', 'ghostCircle show');
        d3.select(domNode).attr('class', 'node activeDrag');

        svgGroup.selectAll("g.node").sort(function(a, b) { // select the parent and sort the path's
            if (a.id != draggingNode.id) return 1; // a is not the hovered element, send "a" to the back
            else return -1; // a is the hovered element, bring "a" to the front
        });
        // if nodes has children, remove the links and nodes
        if (nodes.length > 1) {
            // remove link paths
            links = tree.links(nodes);
            nodePaths = svgGroup.selectAll("path.link")
                .data(links, function(d) {
                    return d.target.id;
                }).remove();
            // remove child nodes
            nodesExit = svgGroup.selectAll("g.node")
                .data(nodes, function(d) {
                    return d.id;
                }).filter(function(d, i) {
                    if (d.id == draggingNode.id) {
                        return false;
                    }
                    return true;
                }).remove();
        }

        // remove parent link
        parentLink = tree.links(tree.nodes(draggingNode.parent));
        svgGroup.selectAll('path.link').filter(function(d, i) {
            if (d.target.id == draggingNode.id) {
                return true;
            }
            return false;
        }).remove();

        dragStarted = null;
    }

    // define the baseSvg, attaching a class for styling and the zoomListener
    var baseSvg = d3.select("#tree-container").append("svg")
        .attr("width", viewerWidth)
        .attr("height", viewerHeight)
        .attr("class", "overlay")
        .call(zoomListener);


    // Define the drag listeners for drag/drop behaviour of nodes.
	var time = 0 
    dragListener = d3.behavior.drag()
        .on("dragstart", function(d) {
			time = performance.now()
            if (d == root) {
                return;
            }
            dragStarted = true;
            nodes = tree.nodes(d);
            d3.event.sourceEvent.stopPropagation();
            // it's important that we suppress the mouseover event on the node being dragged. Otherwise it will absorb the mouseover event and the underlying node will not detect it d3.select(this).attr('pointer-events', 'none');
        })
        .on("drag", function(d) {
			if ( performance.now() - time <= 100 ) return
            if (d == root) {
                return;
            }
            if (dragStarted) {
                domNode = this;
                initiateDrag(d, domNode);
            }

            // get coords of mouseEvent relative to svg container to allow for panning
            relCoords = d3.mouse($('svg').get(0));
            if (relCoords[0] < panBoundary) {
                panTimer = true;
                pan(this, 'left');
            } else if (relCoords[0] > ($('svg').width() - panBoundary)) {

                panTimer = true;
                pan(this, 'right');
            } else if (relCoords[1] < panBoundary) {
                panTimer = true;
                pan(this, 'up');
            } else if (relCoords[1] > ($('svg').height() - panBoundary)) {
                panTimer = true;
                pan(this, 'down');
            } else {
                try {
                    clearTimeout(panTimer);
                } catch (e) {

                }
            }

            d.x0 += d3.event.dy;
            d.y0 += d3.event.dx;
            var node = d3.select(this);
            node.attr("transform", "translate(" + d.y0 + "," + d.x0 + ")");
            updateTempConnector();
        }).on("dragend", function(d) {
            if (d == root) {
                return;
            }
            domNode = this;
            if (selectedNode) {
                // now remove the element from the parent, and insert it into the new elements children
                var index = draggingNode.parent.children.indexOf(draggingNode);
                if (index > -1) {
                    draggingNode.parent.children.splice(index, 1);
                }
                if (typeof selectedNode.children !== 'undefined' || typeof selectedNode._children !== 'undefined') {
                    if (typeof selectedNode.children !== 'undefined') {
                        selectedNode.children.push(draggingNode);
                    } else {
                        selectedNode._children.push(draggingNode);
                    }
                } else {
                    selectedNode.children = [];
                    selectedNode.children.push(draggingNode);
                }
                // Make sure that the node being added to is expanded so user can see added node is correctly moved
                expand(selectedNode);
                sortTree();
                endDrag();
            } else {
                endDrag();
            }
        });

    function endDrag() {
        selectedNode = null;
        d3.selectAll('.ghostCircle').attr('class', 'ghostCircle');
        d3.select(domNode).attr('class', 'node');
        // now restore the mouseover event or we won't be able to drag a 2nd time
        d3.select(domNode).select('.ghostCircle').attr('pointer-events', '');
        updateTempConnector();
        if (draggingNode !== null) {
            update(root);
            centerNode(draggingNode);
            draggingNode = null;
        }
    }

    // Helper functions for collapsing and expanding nodes.

    function collapse(d) {
        if (d.children) {
            d._children = d.children;
            d._children.forEach(collapse);
            d.children = null;
        }
    }

    function expand(d) {
        if (d._children) {
            d.children = d._children;
            d.children.forEach(expand);
            d._children = null;
        }
    }

    var overCircle = function(d) {
        selectedNode = d;
        updateTempConnector();
    };
    var outCircle = function(d) {
        selectedNode = null;
        updateTempConnector();
    };

    // Function to update the temporary connector indicating dragging affiliation
    var updateTempConnector = function() {
        var data = [];
        if (draggingNode !== null && selectedNode !== null) {
            // have to flip the source coordinates since we did this for the existing connectors on the original tree
            data = [{
                source: {
                    x: selectedNode.y0,
                    y: selectedNode.x0
                },
                target: {
                    x: draggingNode.y0,
                    y: draggingNode.x0
                }
            }];
        }
        var link = svgGroup.selectAll(".templink").data(data);

        link.enter().append("path")
            .attr("class", "templink")
            .attr("d", d3.svg.diagonal())
            .attr('pointer-events', 'none');

        link.attr("d", d3.svg.diagonal());

        link.exit().remove();
    };

    // Function to center node when clicked/dropped so node doesn't get lost when collapsing/moving with large amount of children.

    function centerNode(source) {
        scale = zoomListener.scale();
        x = -source.y0;
        y = -source.x0;
        x = x * scale + viewerWidth / 2;
        y = y * scale + viewerHeight / 2;
        d3.select('g').transition()
            .duration(duration)
            .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")");
        zoomListener.scale(scale);
        zoomListener.translate([x, y]);
    }

    // Toggle children function

    function toggleChildren(d) {
        if (d.children) {
            d._children = d.children;
            d.children = null;
        } else if (d._children) {
            d.children = d._children;
            d._children = null;
        }
        return d;
    }

    // Toggle children on click.

    function click(d) {
        if (d3.event.defaultPrevented) return; // click suppressed
        d = toggleChildren(d);
        update(d);
        centerNode(d);
    }

    function update(source) {
        // Compute the new height, function counts total children of root node and sets tree height accordingly.
        // This prevents the layout looking squashed when new nodes are made visible or looking sparse when nodes are removed
        // This makes the layout more consistent.
        var levelWidth = [1];
        var childCount = function(level, n) {

            if (n.children && n.children.length > 0) {
                if (levelWidth.length <= level + 1) levelWidth.push(0);

                levelWidth[level + 1] += n.children.length;
                n.children.forEach(function(d) {
                    childCount(level + 1, d);
                });
            }
        };
        childCount(0, root);
        var newHeight = d3.max(levelWidth) * 25; // 25 pixels per line  
        tree = tree.size([newHeight, viewerWidth]);

        // Compute the new tree layout.
        var nodes = tree.nodes(root).reverse(),
            links = tree.links(nodes);

        // Set widths between levels based on maxLabelLength.
        nodes.forEach(function(d) {
            d.y = (d.depth * (maxLabelLength * 10)); //maxLabelLength * 10px
            // alternatively to keep a fixed scale one can set a fixed depth per level
            // Normalize for fixed-depth by commenting out below line
            // d.y = (d.depth * 500); //500px per level.
        });

        // Update the nodes…
        node = svgGroup.selectAll("g.node")
            .data(nodes, function(d) {
                return d.id || (d.id = ++i);
            });

        // Enter any new nodes at the parent's previous position.
        var nodeEnter = node.enter().append("g")
            .call(dragListener)
            .attr("class", "node")
            .attr("transform", function(d) {
                return "translate(" + source.y0 + "," + source.x0 + ")";
            })
            .on('click', click);

        nodeEnter.append("circle")
            .attr('class', 'nodeCircle')
            .attr("r", 0)
            .style("fill", function(d) {
                return d._children ? "lightsteelblue" : "#fff";
            });

        nodeEnter.append("text")
            .attr("x", function(d) {
                return d.children || d._children ? -10 : 10;
            })
            .attr("dy", ".35em")
            .attr('class', 'nodeText')
            .attr("text-anchor", function(d) {
                return d.children || d._children ? "end" : "start";
            })
            .text(function(d) {
                return d.name;
            })
            .style("fill-opacity", 0);

        // phantom node to give us mouseover in a radius around it
        nodeEnter.append("circle")
            .attr('class', 'ghostCircle')
            .attr("r", 30)
            .attr("opacity", 0.2) // change this to zero to hide the target area
        .style("fill", "red")
            .attr('pointer-events', 'mouseover')
            .on("mouseover", function(node) {
                overCircle(node);
            })
            .on("mouseout", function(node) {
                outCircle(node);
            });

        // Update the text to reflect whether node has children or not.
        node.select('text')
            .attr("x", function(d) {
                return d.children || d._children ? -10 : 10;
            })
            .attr("text-anchor", function(d) {
                return d.children || d._children ? "end" : "start";
            })
            .text(function(d) {
                return d.name;
            });

        // Change the circle fill depending on whether it has children and is collapsed
        node.select("circle.nodeCircle")
            .attr("r", 4.5)
            .style("fill", function(d) {
                return d._children ? "lightsteelblue" : "#fff";
            });

        // Transition nodes to their new position.
        var nodeUpdate = node.transition()
            .duration(duration)
            .attr("transform", function(d) {
                return "translate(" + d.y + "," + d.x + ")";
            });

        // Fade the text in
        nodeUpdate.select("text")
            .style("fill-opacity", 1);

        // Transition exiting nodes to the parent's new position.
        var nodeExit = node.exit().transition()
            .duration(duration)
            .attr("transform", function(d) {
                return "translate(" + source.y + "," + source.x + ")";
            })
            .remove();

        nodeExit.select("circle")
            .attr("r", 0);

        nodeExit.select("text")
            .style("fill-opacity", 0);

        // Update the links…
        var link = svgGroup.selectAll("path.link")
            .data(links, function(d) {
                return d.target.id;
            });

        // Enter any new links at the parent's previous position.
        link.enter().insert("path", "g")
            .attr("class", "link")
            .attr("d", function(d) {
                var o = {
                    x: source.x0,
                    y: source.y0
                };
                return diagonal({
                    source: o,
                    target: o
                });
            });

        // Transition links to their new position.
        link.transition()
            .duration(duration)
            .attr("d", diagonal);

        // Transition exiting nodes to the parent's new position.
        link.exit().transition()
            .duration(duration)
            .attr("d", function(d) {
                var o = {
                    x: source.x,
                    y: source.y
                };
                return diagonal({
                    source: o,
                    target: o
                });
            })
            .remove();

        // Stash the old positions for transition.
        nodes.forEach(function(d) {
            d.x0 = d.x;
            d.y0 = d.y;
        });
    }

    // Append a group which holds all nodes and which the zoom Listener can act upon.
    var svgGroup = baseSvg.append("g");

    // Define the root
    root = treeData;
    root.x0 = viewerHeight / 2;
    root.y0 = 0;
	
	// Collapse all children of roots children before rendering.
	root.children.forEach(function(child){
		collapse(child);
	});

    // Layout the tree initially and center on the root node.
    update(root);
    centerNode(root);
});
This is an example of a collapsible drag and drop tree implementing slightly modified code from https://gist.github.com/robschmuecker/7880033

This is posted in order to demonstrate a viable answer for a Stack Overflow question http://stackoverflow.com/questions/20539922/has-anyone-produced-a-virtualised-javascript-tree-for-thousands-of-nodes

The only difference between this gist and the one referenced above is that the JSON file has changed.  Each node contains 15 children and the depth is 4.  Hence over 50,000 nodes.

The performance is fine if not too many of the nodes are present at once in the DOM.
The JSON was contructed at http://www.json-generator.com/ with the following markup


```JSON
{
        user_id: '{{index}}',
        name: '{{firstName}} {{surname}}',
        children: [
            '{{repeat(15)}}',
            {
                user_id: '{{index}}',
                name: '{{firstName}} {{surname}}',
                children: [
                    '{{repeat(15)}}',
                    {
                        user_id: '{{index}}',
                        name: '{{firstName}} {{surname}}',
                        children: [
                    '{{repeat(15)}}',
                    {
                        user_id: '{{index}}',
                        name: '{{firstName}} {{surname}}',
                        children: [
                        '{{repeat(15)}}',
                    {
                        user_id: '{{index}}',
                        name: '{{firstName}} {{surname}}'
                    }
                        ]
                    }
                ]
                    }
                ]
            }
        ]
}
```

For any help/queries, http://www.robschmuecker.com @robschmuecker or robert.schmuecker at gmail dot com

以上是关于markdown 拖放,可折叠d3.js具有50,000个节点的树的主要内容,如果未能解决你的问题,请参考以下文章

从 CSV 数据创建 D3.js 可折叠树

如何设置 D3.js svg 的背景颜色?

html D3byEX 8.4:拖放(适应D3.js v4)

d3.js之树形折叠树

您知道任何具有水平可折叠窗口或面板等功能的 flex 组件吗?

Markdown中的可折叠标题到html