2013-11-28 113 views
4

我已經修改可摺疊力佈局http://mbostock.github.io/d3/talk/20111116/force-collapsible.html例子中:D3.js堅持父對象在SVG

enter image description here

...現在它看起來像這樣

image

所有的圈子現在都是可拖動的。 我想要堅持中間圈(藍圈)svg的中間。這可能嗎?謝謝。

<script> 

    var width = 960, 
     height = 600, 
     root; 

    var force = d3.layout.force() 
     .linkDistance(175) 
     .charge(-200) 
     .gravity(0) 
     .size([width, height]) 
     .on("tick", tick); 

    var svg = d3.select("body").append("svg") 
     .attr("width", width) 
     .attr("height", height); 

    var link = svg.selectAll(".link"), 
     node = svg.selectAll(".node"); 

    d3.json("graph.json", function(error, json) { 
     root = json; 
     update(); 
    }); 

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

     // Restart the force layout. 
     force 
      .nodes(nodes) 
      .links(links) 
      .start(); 

     // Update links. 
     link = link.data(links, function(d) { return d.target.id; }); 

     link.exit().remove(); 

     link.enter().insert("line", ".node") 
      .attr("class", "link"); 

     // Update nodes. 
     node = node.data(nodes, function(d) { return d.id; }); 

     node.exit().remove(); 

     var nodeEnter = node.enter().append("g") 
      .attr("class", "node") 
      .on("click", click) 
      .call(force.drag) 
      .attr("href", function(d) { return d.link; }); 

    nodeEnter.append("svg:a") 
     .attr("xlink:href", function(d){return d.link;}) 
     .append("circle") 
      .attr("r", function(d) { return Math.sqrt(d.size)/10 || 4.5; }); 

     nodeEnter.append("text") 
      .attr("dy", ".35em") 
      .text(function(d) { return d.name; }); 

     node.select("circle") 
      .style("fill", color); 
    } 

    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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 
    } 

    function color(d) { 
     return d._children ? "#3182bd" // collapsed package 
      : d.children ? "#2F9BC1" // expanded package 
      : "#fd8d3c"; // leaf node 
    } 

    // Toggle children on click. 
    function click(obj) { 
     if (d3.event.defaultPrevented) return; // ignore drag 
     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; 
    } 

    </script> 

JSON文件:

{ 
    "name": "Me", "size": 200000, "link": "http://google.com", 
    "children": [ 
     {"name": "Person 01", "size": 150000, "link": "http://google.com"}, 
     {"name": "Person 02", "size": 150000, "link": "http://yahoo.com"}, 
     {"name": "Person 03", "size": 150000, "link": "http://youtube.com"}, 
     {"name": "Person 04", "size": 150000, "link": "http://twitter.com"}, 
     {"name": "Person 05", "size": 150000, "link": "http://facebook.com"} 
    ] 
} 

回答

3

什麼你需要的做的有問題的節點的fixed屬性已經設置它的座標中心後設置爲true(見the documentation),所以像

nodes.forEach(function(d) { 
    if(d._children || d.children) { 
    d.x = width/2, d.y = height/2; 
    d.fixed = true; 
    } 
}); 

立即在update功能的開始。

如果要禁用該節點的阻力,以及,你可以做

nodeEnter.filter(function(d) { 
      return d.children === undefined && d._children === undefined; 
     }) 
     .call(force.drag); 

,而不是所有節點上調用force.drag。完整示例here

+0

謝謝。追加這個代碼後,中間的圓圈是固定的,但它不在中間。當我重新加載頁面時,位置會隨機變化。而我想禁用中圈拖動效果。 –

+1

我已經更新了答案。 –

+0

這是一個完美的答案。非常感謝你的大力幫助。 –