2015-12-03 73 views
0

我使用D3的強制佈局來顯示圖形。現在,我需要在任何節點被點擊時節點改變它們的位置。在d3強制佈局中移動固定節點

我擡頭看了其他相關的StackOverflow問題,但這並沒有幫助我。

用於渲染的代碼如下:

var render = function(graph){ 

     /* var loading = svg.append("text") 
      .attr("x", width/2) 
      .attr("y", height/2) 
      .attr("dy", ".35em") 
      .style("text-anchor", "middle") 
      .text("Simulating. One moment please…");*/ 


     force 
      .nodes(graph.nodes) 
      .links(graph.links) 
      .start(); 

     var link = svg.selectAll(".link") 
      .data(graph.links); 

     //Enter phase for links. 
     link.enter().append("line"); 

     //Update phase for links 
      link 
      .attr("class", "link") 
      .style("stroke-width", function(d) { return Math.sqrt(d.value); }); 

     var node = svg.selectAll(".node") 
      .data(graph.nodes,function(d){return d.name;}); 

     //Enter phase for nodes 
     var node_g = node.enter() 
      .append("g") 
      .attr("class","node") 
      .on("dblclick",nodeClick) 
      .call(force.drag); 

     //Update phase for nodes 

     node_g.append("text") 
      .attr("class","NodeLabel") 
      .text(function(d){ 
       return d.name; 
      }); 

     var nodeCirlce = node_g.append("circle"); 

     nodeCirlce 
      .attr("r", 5) 
      .style("fill", function(d) { return color(d.group); }) 

     node_g.append("title") 
      .text(function(d) { return d.name; }); 

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

      //TODO : Add attr change for node text as well. 
     }); 

而對於節點單擊處理代碼如下所示:

var nodeClick = function(d,i){ 
     //Translate the graph to center around the selected node. 
     var x_trans = x_cent - d.x; 
     var y_trans = y_cent - d.y; 
     var nodes = oldGraph.nodes; 

     for(var i=0;i<nodes.length;i++){ 
      var node = nodes[i]; 
      node.x = node.x + 1000; 
      node.y = node.y + 1000; 
      node.fixed = true; 
     } 
     //oldGraph.nodes = updateNodes(nodes,oldGraph.links); 
     render(oldGraph); 
     //setTimeout(function(){layout("json/HUMAN-1g.json");},000); 

    }; 

然而,節點位置沒有更新。

+0

更新數據後需要調用'tick'處理函數。 –

+0

@LarsKotthoff:試過了,沒有奏效。修改渲染函數如下: force .nodes(graph.nodes) .links(graph.links); force.start(); for(var i = n * n; i> 0; --i)force.tick(); force.stop(); var link = svg.selectAll(「.link」) .data(graph.links); ...... }); 我也刪除了force.on處理程序。 (代替節點和鏈接的更新階段後沒有處理程序的代碼) – Sheno

+0

你可以把它放在小提琴上嗎...... – Cyril

回答

1

更改數據後,您需要運行更新DOM中位置的代碼。這正是你在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_g.attr("transform",function(d){ 
       return "translate("+ d.x+","+ d.y+")"; 

我建議拉這個到一個單獨的函數,然後將其設置爲tick處理函數,並從nodeClick()函數調用它。要清楚,你不需要需要調用render()nodeClick()函數。

+0

謝謝。這有很大幫助。 我從徑向樹佈局移動到強制佈局,並試圖類似地複製代碼。 – Sheno

相關問題