2015-12-03 74 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

相关问题