2012-07-21 20 views
29

Estoy utilizando un árbol d3.js y me gustaría agregar nodos dinámicamente, en lugar de precargar todo el árbol.d3.js cómo agregar nodos dinámicamente a un árbol

¿Cómo puedo modificar lo siguiente para agregar dinámicamente nodos JSON adicionales cuando se hace clic en un nodo? (Ver enlace más abajo, y el código de abajo)

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

Así que en lugar de pre-carga de todo el árbol, en lugar me gustaría recuperar los nodos hijos sólo cuando se hace clic en el padre. Puedo recuperar el json para los nodos secundarios en la función de alternar, sin embargo, no puedo entender cómo puedo agregarlos al árbol.

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

Respuesta

24

que fue capaz de añadir dinámicamente nodos añadiendo el código siguiente en la función de palanca:

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

Notas: estoy usando jQuery para recuperar el archivo JSON

+0

¿De dónde viene esa función de actualización? – Fatih

+0

¿Qué quieres decir? Está en el código en mi pregunta anterior. –

+1

Ah, a la derecha. No pude darme cuenta de que eres la misma persona. ¡Mi error! – Fatih

0

Soy nuevo a D3, pero este código sin procesar podría ser útil. Puede crear un objeto JSON e insertarlo en el árbol/enlace. Entonces solo es cuestión de volver a dibujar el árbol.

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