2014-10-06 848 views
1

注意:我的第一个StackOverFlow帖子请耐心等待。在D3.js中动态创建节点

的目的我的代码:

  • 采取的连通图在用户友好的方式输入(我的意思是用户应该能够添加一个节点发言权,双击。当用户想要连接两个节点时,他/她可能只需选择两个节点,并且应该有一种方式让用户输入两个选定节点之间的距离)。例如,我想对图形执行各种操作,例如告诉节点'A'到节点'B'的最短路径是什么。

方法:

我已决定使用D3.js为宗旨。我是JavaScript/jQuery的新手,但我仍然从https://www.dashingd3js.com/table-of-contents了解到D3.js。 我已经看到人们用D3.js创建了包含图的令人惊叹的漂亮项目,但即使在基础知识中我也有点挣扎。

尝试:

我写了下面的代码连接两个节点:我面临

<!DOCTYPE html> 
<html> 

<head> 
<title>D3 Try</title> 
<script type="text/javascript" src="d3.min.js"></script> 

</head> 

<style> 

.node { 
    fill: #ccc; 
    stroke: #fff; 
    stroke-width: 2px; 
} 

.link { 
    stroke: #777; 
    stroke-width: 2px; 
} 

    </style> 
<body style="background-color: red"> 

<h2>Hello world</h2> 

<script type="text/javascript"> 

var height=500,width=960; 

// If we leave out the x and y coordinates of the visualization, d3 selects 
// random positions for the nodes 

// nodes are arbitrary objects 

var nodes = [ {x: width/3, y: height/2 } , {x: 2*width/3, y: height/2} ]; 

// Define the array which contains information about the links 

var links= [ {source: 0, target: 1}]; 


// container to hold the visualisation 

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

// Create force layout object which contains dimensions of the container and 
// the arrays of nodes and links 


var force=d3.layout.force().size([width,height]).nodes(nodes).links(links); 



// Documentation says that define a function in place of width/2 but fir bhi , how? 


force.linkDistance(width/2); 



var link=svg.selectAll('.link').data(links).enter().append('line').attr('class','link'); 

var node=svg.selectAll('.node').data(nodes).enter().append('circle').attr('class','node'); 



force.on('end',function(){ 




node.attr('r', width/25) 
     .attr('cx', function(d) { return d.x; }) 
     .attr('cy', function(d) { return d.y; }); 



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; }); 


}); 


force.start(); 








</script> 





</body> 

</html> 

问题,什么我真想问:

  1. 的上面的代码连接两个节点,好吧,但我该如何在用户d上动态创建这样的节点双击?在这里可以注意到,不仅节点必须是在SVG上绘制为,而且还要更新nodeslinks阵列。我如何动态更新这些硬编码数组,以便将最新信息存储在它们中?

  2. 在两个节点之间的距离必须由用户输入,在这里它是一个恒定width/2。我检查了github上的API,他们说定义了一个函数,而不是一个常量。我搜索了但找不到任何示例。即使我使用D3提供的变量d,由于它必须依赖于用户,因此它是无用的。

任何帮助?谢谢。

回答

0

要做到这一点,你可以依靠D3 .enter()方法的魔力。这是一个对选择进行操作的数据,并为分配给当前未映射到DOM中的SVG元素的选择的每个数据返回一个占位符。

这意味着,如果你修改数据,然后可以将数据追加到一个选择,并有由在选择的变化表示的数据的任何变化。如果你想一个节点添加到您的数据,它的工作是这样的:

//Modify data 
nodes.push({x : d3.mouse(svg)[0], y : d3.mouse(svg)[1]}); 

//Modify data of node selection 
node.data(nodes); 

//Operate on new nodes 
node.enter() 
    .append('circle') 
    .attr('class','node') 
    .attr('r', width/25) 
    .attr('cx', function(d) { return d.x; }) 
    .attr('cy', function(d) { return d.y; }); 
    .call(force.end); 

因为你的前两个数据点已经有DOM节点分配给他们当你第一次创建它们,这样只会追加新用于新数据点的circle元素。

所有这些都会在mousedownclick的事件处理函数中调用,并且会以鼠标位置的形式接受用户输入。

+0

是的。我知道了。 'd3.mouse(svg)[0]'返回x坐标和y坐标,然后更新节点。对?但是,您能告诉我如何获得用户的节点之间的距离作为输入吗? – Dash 2014-10-06 18:24:01

+0

你如何期待用户输入距离? – ckersch 2014-10-06 18:30:24