2013-07-06 76 views
1

我的目標是在所有節點摺疊後開始佈局,單擊它們展開。這裏的問題是文本標籤在mouseover上創建重複項。他們還在屏幕的左上角創建重複項。啓動d3強制佈局摺疊,複製文本標籤

我已經減少了測試的最小量JSON,這是低於代碼塊。

我在做什麼錯?

<!DOCTYPE html> 
<html> 
    <head> 
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> 
    <title>Force-Directed Graph</title> 
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> 
    <style type="text/css"> 

circle.node { 
    cursor: pointer; 
    stroke: #3182bd; 
    stroke-width: 1.5px; 
} 

line.link { 
    fill: none; 
    stroke: #9ecae1; 
    stroke-width: 1.5px; 
} 

    </style> 
    </head> 
    <body> 
    <div id="chart"></div> 
    <script type="text/javascript"> 

var w = 960, 
    h = 500, 
    node, 
    link, 
    root, 
    t; 

var force = d3.layout.force() 
    .on("tick", tick) 
    .size([w, h]); 

var vis = d3.select("#chart").append("svg:svg") 
    .attr("width", w) 
    .attr("height", h); 

d3.json("test.json", function(json) { 
    root = json; 
    update(); 

function toggleAll(d) { 
    if (d.children) { 
     d.children.forEach(toggleAll); 
     toggle(d); 
    } 
    } 
    // Initialize the display to show a few nodes. 
    root.children.forEach(toggleAll); 


update(root); 
}); 

function update() { 
    var nodes = flatten(root), 
     links = d3.layout.tree().links(nodes); 

    // Restart the force layout. 
    force 
     .nodes(nodes) 
     .links(links) 
     .charge(-1000) 
    .linkDistance(100) 
    .friction(0.5) 
     .start(); 

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

    // Enter any new links. 
    link.enter().insert("svg:line", ".node") 
     .attr("class", "link") 
     .attr("x1", function(d) { return d.source.x; }) 
     .attr("y1", function(d) { return d.source.y; }) 
     .attr("x2", function(d) { return d.target.x; }) 
     .attr("y2", function(d) { return d.target.y; }); 

    // Exit any old links. 
    link.exit().remove(); 

    // Update the nodes… 
    node = vis.selectAll("circle.node") 
     .data(nodes, function(d) { return d.id; }) 
     .style("fill", color); 

    // Enter any new nodes. 
    node.enter().append("svg:circle") 
     .attr("class", "node") 
     .attr("cx", function(d) { return d.x; }) 
     .attr("cy", function(d) { return d.y; }) 
     .attr("r", "15") 
     .style("fill", color) 
     .on("mouseover", mouseover)  
     .call(force.drag); 

    // Exit any old nodes. 
    node.exit().remove(); 

    t = vis.selectAll("t.node") 
     .data(nodes, function(d) { return d.id; }) 
     .style("fill", color); 

    // Enter any new nodes. 
    t.enter().append("svg:text") 
     .attr("class", "t-node") 
     .attr("dx", "25px") 
     .attr("y", 0) 
     .text("test"); 
    // .call(force.drag); 

    // Exit any old nodes. 
    t.exit().remove(); 

} 

function tick() { 
    link.attr("x1", function(d) { return d.source.x; }) 
     .attr("y1", function(d) { return d.source.y; }) 
     .attr("x2", function(d) { return d.target.x; }) 
     .attr("y2", function(d) { return d.target.y; }); 

    node.attr("cx", function(d) { return d.x; }) 
     .attr("cy", function(d) { return d.y; }); 

    t.attr("x", function(d) { return d.x; }) 
     .attr("y", function(d) { return d.y; }); 
// t.attr("transform", function(d) { 
//  return "translate(" + d.x + "," + d.y + ")"; }) 

} 

// Color leaf nodes orange, and packages white or blue. 
function color(d) { 
    return d._children ? "#3182bd" : d.children ? "#c6dbef" : "#fd8d3c"; 
} 

// Toggle children on click. 
function mouseover(d) { 
    if (d.children) { 
    d._children = d.children; 
    d.children = null; 
    } else { 
    d.children = d._children; 
    d._children = null; 
    } 
    update(); 
} 

// Returns a list of all nodes under the root. 
function flatten(root) { 
    var nodes = [], i = 0; 

    function recurse(node) { 
    if (node.children) node.children.forEach(recurse); 
    if (!node.id) node.id = ++i; 
    nodes.push(node); 
    } 

    recurse(root); 
    return nodes; 
} 
function toggle(d) { 
    if (d.children) { 
    d._children = d.children; 
    d.children = null; 
    } else { 
    d.children = d._children; 
    d._children = null; 
    } 
} 
    </script> 
    </body> 
</html> 

    { 
"name": "Test", 
"children": [ 
    { 
    "name": "cat 1", 
    "children": [ 
    {"name": "subcat 1-a", "size": 1082}, 
    {"name": "subcat 1-b", "size": 1082} 
    ] 
    }, 
    { 
    "name": "cat 2", 
    "children": [ 
    {"name": "subcat 2-a", "size": 1082} 
    ] 
    } 
] 
} 
+0

關鍵是您需要修改您作爲節點傳遞的數據結構,並鏈接到強制佈局,而不是傳入新的數據結構。因此,請保留鏈接和節點列表並添加到/從中刪除,而不是在'update'函數中重新計算它。 –

+0

感謝您的澄清,有沒有一個基於代碼的例子,你知道這個例子證明了這一點? – sn4ke

+0

D3例子中有幾個例子,例如[this one](http://bl.ocks.org/rkirsling/5001347)。 –

回答

2

竊取@Lars'回答的風險,vis.selectAll("t.node")看起來像它需要vis.selectAll(".t-node")。如果您在selectAll中沒有使用與您在.enter()選擇中附加的節點相匹配的選擇器,則每次運行時都會得到重複的節點。

+0

解決了這個問題,謝謝! – sn4ke