2014-11-21 71 views
0

我在d3.js裏呆了兩天,並且我已經構建了這個用於網球錦標賽的繪製結構。需要d3.js邏輯才能在JSON數據上工作

enter image description here

而且我先從數據低於 -

var data = [ 
 
      [["Andy","Marin"],["David","Kei"],["Novak","Stani"],["Roger","Gael"],["Phili","John"],["Milos","Rafa"],["Tomas","Grig"],["Jo-Wi","Gill"]], 
 
      [["Marin","Kei"],["Stani","Roger"],["John","Rafa"],["Tomas","Jo-Wi"]], 
 
      [["Marin","Stani"],["John","Jo-Wi"]], 
 
      [["Stani","John"]] 
 
      ];

我不知道如何,但我到下面的代碼來實現這一點(我使用了很多mbostock的代碼) -

var playerOffsetX = 20; 
 
\t rectY= 20; 
 
\t rectGapY = 10; 
 
\t matchGapY = 30; 
 
\t rectX = 100; 
 
\t matchY = 2 * rectY + rectGapY + matchGapY; 
 
\t totalY = 8 * matchY; 
 

 
var svg = d3.selectAll("svg"); 
 

 
var level = svg.selectAll(".level") 
 
\t \t .data(data) 
 
\t .enter().append("g") 
 
\t \t .attr("transform", function(d, i) { return "translate(" + (i * 200) + "," + Math.pow(2,i)*matchY/2 + ")"; }) 
 
\t \t .attr("class", "level"); 
 

 
var match = level.selectAll(".match") 
 
\t \t .data(function(d) { return d ; }) 
 
\t .enter().append("g") 
 
\t \t .attr("transform", function(d, i, j) { return "translate(0," + (Math.pow(2,j)*i*matchY) + ")"; }) 
 
\t \t .attr("class", "match"); 
 
\t \t 
 
var player = match.selectAll(".player") 
 
\t .data(function(d) { return d; }) 
 
\t .enter() 
 
\t .append("g") \t 
 
\t \t .attr("transform", function(d, i) { return "translate("+ (playerOffsetX) + "," + (i == 0 ? 0 : (rectY+rectGapY)) + ")"; }) 
 
\t \t .attr("class", "player"); 
 
\t \t 
 
player.append("rect") 
 
\t .attr("width", rectX) 
 
\t .attr("height", rectY) 
 
\t .attr("class", "player"); 
 
\t 
 
player.append("text") 
 
\t .attr("x", 3) 
 
\t .attr("y", rectY/2) 
 
\t .attr("dy", ".35em") 
 
\t .text(function(d) { return d; }); 
 

 
</script>

現在這是我的問題。我想通過數據,因爲這給重組 -

var data = [{ "level": 1, "matches": [{"seq": 1, "seeds": [1,16]}, {"seq": 2, "seeds": [8,9]}, {"seq": 3, "seeds": [4,13]}, {"seq": 4, "seeds": [5,12]}, 
 
           \t \t {"seq": 5, "seeds": [2,15]}, {"seq": 6, "seeds": [7,10]}, {"seq": 7, "seeds": [3,14]}, {"seq": 8, "seeds": [6,11]}]}, 
 
      { "level": 2, "matches": [{"seq": 9, "seeds": [0,0]}, {"seq": 10, "seeds": [0,0]}, {"seq": 11, "seeds": [0,0]}, {"seq": 12, "seeds": [0,0]}]}, 
 
      { "level": 3, "matches": [{"seq": 13, "seeds": [0,0]}, "seq": 14, "seeds": [0,0]}]}, 
 
      { "level": 4, "matches": [{"seq": 15, "seeds": [0,0]}]}];

...我想不出我應該在我的代碼更改。

當然,我還有一個問題。你可以看到,我沒有連接跨越水平的獲勝者的鏈接。我需要他們。我考慮過集羣佈局,但我想我將不得不根據數據進行重組來適應。我的情況與羣集情況完全相反。 (Mukul)

回答

1

你希望它變成的結構應該和原始結構一樣好,因爲它基本上仍然是一個三層數組,因爲你現在正在將物體包裝在對象中,所以你有調整渲染時子數組的訪問方式。我已標記的3個地方像<-- THIS

var level = svg.selectAll(".level") 
    .data(data) 
    .enter().append("g") 
    .attr("transform", function(d, i) { return "translate(" + (i * 200) + "," + Math.pow(2,i)*matchY/2 + ")"; }) 
    .attr("class", "level"); 

var match = level.selectAll(".match") 
    .data(function(d) { return d.matches ; })// <-- THIS 
    .enter().append("g") 
    .attr("transform", function(d, i, j) { return "translate(0," + (Math.pow(2,j)*i*matchY) + ")"; }) 
    .attr("class", "match"); 

var player = match.selectAll(".player") 
    .data(function(d) { return d.seeds; })// <-- THIS 
    .enter() 
    .append("g") 
    .attr("transform", function(d, i) { return "translate("+ (playerOffsetX) + "," + (i == 0 ? 0 : (rectY+rectGapY)) + ")"; }) 
    .attr("class", "player"); 

player.append("rect") 
    .attr("width", rectX) 
    .attr("height", rectY) 
    .attr("class", "player"); 

player.append("text") 
    .attr("x", 3) 
    .attr("y", rectY/2) 
    .attr("dy", ".35em") 
    .text(function(d) { return getPlayerByIdOrSomethingLikeThat(d); });// <-- THIS 

除非我忽視的東西,這會工作。

關於第二個問題,我認爲力佈局(不是集羣)就是你想要看和學習的 - 不是因爲力佈局是移動節點(你不是),而是因爲大多數力佈局示例具有節點和鏈接(您也可以這樣做)。在這種情況下,你想表達的鏈接作爲映射sourcetarget對象數組:

[ 
    { source: {...}, target: {...} }, 
    { source: {...}, target: {...} }, 
    { source: {...}, target: {...} }, 
    ... 
] 

因爲這樣你可以做全d3.select(...).selectAll(...).data(...).enter().append('line')照常營業,以連接它們的線路追加。即這很方便,因爲它是源到目標對與SVG <line>之間的1到1映射)。所以你有一個任務是弄清楚如何從數據結構中提取這些鏈接。但在此之前,你必須弄清楚sourcetarget究竟是什麼,我不完全確定什麼效果最好。它不能只是一個玩家對象,因爲在你的情況下,它是兩個地方的同一個玩家。因此,sourcetarget也必須封裝level,無論如何,您需要level以確定行的每一端的x位置。而seqsourcetarget中您需要的第三件事,因爲這是確定行的y位置的方式。我的建議是將兩個這樣的鏈接手動編碼到links數組中,然後弄清楚如何將它們渲染爲線。一旦你到達了一個有效的方式,找出如何編程links,從data。希望有所幫助。

+0

嘿meetamit - 非常感謝。該解決方案有效。當然,我發佈的json樣本有錯誤,但你有這個想法。讓我將'源碼 - 目標'合併到我的代碼中。 – brevitylabs 2014-11-22 08:30:03

+0

進一步更新 - 我已將較早的邏輯(後來由@meetamit更正)拋出窗口。強制佈局使用我的代碼精簡地減少了70%。對我的第三天的d3.js不壞乾杯。 – brevitylabs 2014-11-22 10:19:12