2012-07-21 6 views
29

Ich benutze einen d3.js-Baum, und möchte Knoten dynamisch hinzufügen, anstatt den gesamten Baum vorab laden.d3.js wie Knoten dynamisch zu einem Baum hinzufügen

Wie würde ich Folgendes ändern, um beim Klicken auf einen Knoten dynamisch weitere JSON-Knoten hinzuzufügen? (Siehe Link unten, und Code unten)

http://mbostock.github.com/d3/talk/20111018/tree.html

Also anstatt den gesamten Baum Vorbelastung, stattdessen würde Ich mag das Kind zurückzuholen Knoten nur, wenn die Eltern angeklickt wird. Ich kann die JSON für die Kind-Knoten in der Toggle-Funktion abrufen, aber ich kann nicht herausfinden, wie ich sie zum Baum hinzufügen kann.

var m = [20, 120, 20, 120], 
    w = 1280 - m[1] - m[3], 
    h = 800 - m[0] - m[2], 
    i = 0, 
    root; 

var tree = d3.layout.tree() 
    .size([h, w]); 

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

var vis = d3.select("#body").append("svg:svg") 
    .attr("width", w + m[1] + m[3]) 
    .attr("height", h + m[0] + m[2]) 
    .append("svg:g") 
    .attr("transform", "translate(" + m[3] + "," + m[0] + ")"); 

d3.json("flare.json", function(json) { 
    root = json; 
    root.x0 = h/2; 
    root.y0 = 0; 

    function toggleAll(d) { 
    if (d.children) { 
     d.children.forEach(toggleAll); 
     toggle(d); 
    } 
    } 

    // Initialize the display to show a few nodes. 
    root.children.forEach(toggleAll); 
    toggle(root.children[1]); 
    toggle(root.children[1].children[2]); 
    toggle(root.children[9]); 
    toggle(root.children[9].children[0]); 

    update(root); 
}); 

function update(source) { 
    var duration = d3.event && d3.event.altKey ? 5000 : 500; 

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

    // Normalize for fixed-depth. 
    nodes.forEach(function(d) { d.y = d.depth * 180; }); 

    // Update the nodes… 
    var node = vis.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("svg:g") 
     .attr("class", "node") 
     .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; }) 
     .on("click", function(d) { toggle(d); update(d); }); 

    nodeEnter.append("svg:circle") 
     .attr("r", 1e-6) 
     .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); 

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

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

    nodeUpdate.select("circle") 
     .attr("r", 4.5) 
     .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); 

    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", 1e-6); 

    nodeExit.select("text") 
     .style("fill-opacity", 1e-6); 

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

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

    // 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; 
    }); 
} 

// Toggle children. 
function toggle(d) { 

    // I could retrieve the child nodes here, but how to add them to the tree? 

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

Antwort

24

Ich war in der Lage, dynamisch Knoten hinzufügen, indem Sie den folgenden Code in der Toggle-Funktion hinzugefügt:

$.getJSON(addthese.json, function(addTheseJSON) { 
    var newnodes = tree.nodes(addTheseJSON.children).reverse(); 
    d.children = newnodes[0]; 
    update(d); 
}); 

Anmerkungen: Ich bin mit jQuery JSON-Datei abrufen

+0

Woher kommt diese Update-Funktion? – Fatih

+0

Was meinst du? Es ist in dem Code in meiner Frage oben. –

+1

Ah, richtig. Ich konnte nicht erkennen, dass du dieselbe Person bist. Mein Fehler! – Fatih

0

Ich bin neu zu D3, aber dieser rohe Code könnte hilfreich sein. Sie können ein JSON-Objekt erstellen und es in den Baum/Link schieben. Dann geht es nur darum, den Baum neu zu zeichnen.

function createTreeNode(source){ 

var current_node = tree.nodes(source); 
var myJSONObject = {"name": "new Node","children": []}; 

if(current_node[0]._children!=null){ 
current_node[0]._children.push(myJSONObject); 
console.log(current_node[0]._children); 
source.children = source._children; 
source._children = null; 
} 

else if(current_node[0].children!=null && current_node[0]._children!=null){ 
current_node[0].children.push(myJSONObject); 
console.log(current_node[0].children); 
} 

else{ 
current_node[0].children=[] 
current_node[0].children.push(myJSONObject); 
console.log(current_node[0].children); 
} 

tree.links(current_node).push(current_node[current_node.length-1]); 
navigate_tree(source);}