2012-07-21 30 views
29

私はd3.jsツリーを使用しており、ツリー全体を事前にロードするのではなく、動的にノードを追加したいと考えています。d3.jsツリーにノードを動的に追加する方法

ノードをクリックしたときに追加のJSONノードを動的に追加するにはどうすればよいですか?代わりに、私は子供が親がクリックされたときにのみノード取得したいと思い、

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

そうではなく、ツリー全体を事前にロードする(下記のリンク、および以下のコードを参照してください)。私はトグル関数で子ノードのjsonを取得することができますが、私はどのようにツリーに追加することができないのか分かりません。

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

答えて

24

私は動的にトグル機能に次のコードを追加することにより、ノードを追加することができました:

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

注:私は、私は新たなんだJSONファイル

+0

このアップデート機能はどこにありますか? – Fatih

+0

どういう意味ですか?上記の私の質問のコードにあります。 –

+1

ああ、そうです。私はあなたが同じ人であることを理解できませんでした。私の悪い! – Fatih

0

を取得するためにjQueryを使用していますD3には、この生のコードが役立つ可能性があります。 JSONオブジェクトを作成し、それをツリー/リンクにプッシュすることができます。その後、ツリーを再描画するだけです。

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