2013-04-19 39 views
3

我有一個javascript對象數組,其中每個對象都有.ui屬性,它包含一個現有的 SVG形狀/各種元素(一個自包含的「g」元素與其他人一起)。如何使用D3強制佈局與現有的SVG元素作爲節點

我想將這些對象安排爲D3中的強制圖佈局。因此,我不想讓d3創建圓圈(或其他),而是要將我的一個ui對象分配給圖形。我爲此創建了simplified fiddle << HERE >>。預先存在且應該是圖形一部分的對象是3個彩色矩形。在這個例子中,我沒有做到這一點。 d3 附加命令只能用於構造形狀/元素,但不能附加已經構建的形狀/元素。我試圖做到這一點,它不能在D3工作:

node.append(function(d) { d.ui.node(); }) ... 

...如前所述,這不會工作,爲d3不追加要素。

var svgContainer = d3.select("#svgContainer"); 

// =============================================================  
// creates the SVG elements to be used (3 colored rectangles) 
// ============================================================= 

var element0a = svgContainer.append("g").attr("transform","translate(100,100)"); 
var element0b = element0a.append("rect").attr("x",0).attr("y",0).attr("width",20).attr("height",10).attr("fill","red"); 

var element1a = svgContainer.append("g").attr("transform","translate(100,200)"); 
var element1b = element1a.append("rect").attr("x",0).attr("y",0).attr("width",20).attr("height",10).attr("fill","green"); 

var element2a = svgContainer.append("g").attr("transform","translate(100,300)"); 
var element2b = element2a.append("rect").attr("x",0).attr("y",0).attr("width",20).attr("height",10).attr("fill","blue"); 

// ============================================================= 
// fills up an object array that contains details plus the UI attribute 
// ============================================================= 

var nodeArray = new Array(); 
nodeArray[0] = { id : "000", label : "label 000", ui : element0a }; 
nodeArray[1] = { id : "001", label : "label 001", ui : element1a }; 
nodeArray[2] = { id : "002", label : "label 002", ui : element2a }; 

// not interested in dealing with the edge/link right now, just empty 
var linkArray = new Array(); 


// ============================================================= 
// D3 force layout stuff 
// ============================================================= 

var force = self.force = d3.layout.force() 
    .nodes(nodeArray) 
    .links(linkArray) 
    .gravity(.05) 
    .distance(80) 
    .charge(-100) 
    .size([600, 600]) 
    .start(); 

var node = svgContainer.selectAll("g.node") 
    .data(nodeArray) 
    .enter().append("svg:g") 
    .attr("class", "node") 
    .call(force.drag); 

// HERE (below) COMES THE ISSUE, where you see append("cicle") I want to append the nodeArray's ".ui" element. 

node.append("circle")   // <--- 
    .attr("class", "node") 
    .attr("r",10) 
    .attr("fill","orange") 
    .call(force.drag); 

force.on("tick", function() { 
     node.attr("transform", function(d) {return "translate(" + d.x + "," + d.y + ")";}); 
    }); 
+2

您應該可以使用'.select()'來選擇已經存在的元素。你可能想給他們個人ID,這將使他們更容易選擇。 –

+0

好的建議。事實上,我不應該使用** enter()**階段,而應該簡單地選擇現有的元素。總體而言,如果您不需要創建,則不需要輸入()。 – gextra

回答

3

基於建議從Lars Kotfoff

工作撥弄here

如果元素是圖表-ED已經存在,簡單地跳過輸入() D3相,並使用選擇()或全選( )基於你的元素的共同特徵(例如類名)。

這是該元件得到了如何創建的(添加了一個特定的類,以允許分離的選擇):

var element0a = svgContainer.append("g").attr("class","node").attr("transform","translate(100,100)"); 
var element0b = element0a.append("rect").attr("x",0).attr("y",0).attr("width",20).attr("height",10).attr("fill","red"); 

這是代碼替換輸入()相

var node = svgContainer.selectAll("g.node") 
    .data(nodeArray) 
    .call(force.drag); 

的thene部分這是刪除的內容

var node = svgContainer.selectAll("g.node") 
    .data(nodeArray) 
    .enter().append("svg:g") 
    .attr("class", "node") 
    .call(force.drag); 

// HERE (below) COMES THE ISSUE, where you see append("cicle") I want to append the nodeArray's ".ui" element. 

node.append("circle")   // <--- 
    .attr("class", "node") 
    .attr("r",10) 
    .attr("fill","orange") 
    .call(force.drag); 
0

的問題是,你追加元素svgContainer創建它們,因此它們已經連接到一些東西。

我建議作爲一種解決方法是將元素屬性存儲在json文件中,然後從json中讀取配置。

可能有更優雅的東西。

相關問題