2015-12-30 24 views
0

在我的D3 force布局中,当我动态添加圆圈和链接时,链接的长度有时会增加到无穷大。添加更多节点后,它会自动更正。节点之间链接的不可预知的长度

enter image description here

的代码是

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 

.node { 
    stroke: #fff; 
    stroke-width: 1.5px; 
} 

.link { 
    stroke: #999; 
    stroke-opacity: .6; 
} 

</style> 
<body> 
<script src="d3.min.js"></script> 

<script> 


    // var in1=prompt("Name"); 
    // var in2=prompt("Name"); 

var n= new Array(); 
var l=new Array(); 

var n=[]; 
var l=[]; 



    function show() 
    { 


var width = 960, 
    height = 500; 

var color = d3.scale.category20(); 

var force = d3.layout.force() 
    .charge(-120) 
    .linkDistance(30) 
    .size([width, height]); 


d3.select("svg").remove(); 

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






    force 
     .nodes(n) 
     .links(l) 
     .start(); 

    var link = svg.selectAll(".link") 
     .data(l) 
    .enter().append("line") 
     .attr("class", "link") 
     .style("stroke-width", function(d) { return Math.sqrt(d.value); }); 

    var node = svg.selectAll(".node") 
     .data(n) 
     .enter().append("circle") 
     .attr("class", "node") 
     .attr("r", 5) 
     .style("fill", function(d) { return color(d.group); }) 
     .call(force.drag); 




    node.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.attr("cx", function(d) { return d.x; }) 
     .attr("cy", function(d) { return d.y; }); 
    }); 




} 




function add() 
{ 
    try{ 


    var add_name=prompt("name","Name"); 
    var add_group=parseInt(prompt("group","0")); 

    n.push({"name":add_name,"group":add_group}); 

    if(n.length>1) 
    { 
    var add_source=parseInt(prompt("source","0")); 
    var add_target=parseInt(prompt("target","0")); 
    var add_value=parseInt(prompt("value","0")); 



    l.push({"source":add_source,"target":add_target,"value":add_value}); 

    console.log(n); 
    console.log(l); 
    } 

    show(); 
} 


catch(e) 
{ 
    console.log(e); 
} 


} 



</script> 

<body onload="show();"> 
<input type="button" onclick="add();" value="dd"> 

回答

1

我认为这个问题是您要添加一个节点的布局,而模拟仍在进行中。如果我添加了一个节点并快速添加另一个节点,我能够重现该问题。

一种可能性是在您的add()函数中通过调用force layout's stop() method来停止布局。您需要在show()函数之外声明force变量,与您声明节点列表n和链接l的方式相同。

另一种可能更好的方法是只创建一次力布局。目前,您在页面加载时创建一个强制布局,并为添加的每个附加节点创建一个额外的强制布局。更新节点和链接列表时仍会出现问题,这些节点和链接仍由正在后台运行的“旧”力布局使用。如果只创建了一个强制布局,则不需要停止它:只需调用它的start()方法,即可在修改正在运行的数据后重新初始化它自己。

+0

不需要调用'.stop()'方法。主要部分是调用'.start()'方法,该方法将对内部设置强制布局所需的距离,链接强度,费用等进行初始计算。您可以随时调用'.start()',即使布局仍在运行,它将执行一个新的init并重新启动布局。这[示例](http://bl.ocks.org/mbostock/1095795)显示,它是如何完成的。 – altocumulus

+0

@altocumulus:在这种情况下,最好不要在每次添加节点时创建一个新的强制布局,因为OP的代码目前是这样做的。我已经更新了我的答案。 –

+0

我甚至错过了在每次添加时创建新布局的细节。这进一步恶化了事情,并且是一个非常有问题的方法。你的第二个选择是要走的路。 – altocumulus