2014-10-06 849 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