2013-12-10 53 views
8

的子陣列我有以下結構:D3:對象

[ 
    { 'length': 10, attributes: [1,2,3] }, 
    { 'length': 7, attributes: [1,3,4,5] }, 
    { 'length': 12, attributes: [3,5,7,9,10] }, 
] 

and I am doing the following: 


x = d3.scale.linear().domain([0, maxHeight]).range([50, w]), 
y = d3.scale.linear().domain([0, maxHeight]).range([h, 20]); 
z = d3.scale.linear().domain([0, maxHeight]).range([0, h - 20]); 

var chart = svg.selectAll("g.chart") 
    .data(items) 
    .enter() 
    .append("svg:g") 
    .attr("class", "chart"); 

chart.append("svg:rect") 
    .attr("fill", 'darkblue') 
    .attr("class", 'data') 
    .attr("x", function(d, i) { return x(i+1); }) 
    .attr("y", function(d, i) { return bottom - z(d['length']) + 15 }) 
    .attr("width", 4) 
    .attr("height", function(d, i) { return z(d['length']) - z(d['min']); }) 

我想這樣做是對每個矩形對應於在我的結構屬性的社交圈。基本上,(一個「項目」},我應該看到這樣的事情:

<g class="chart"> 
    <rect fill="darkblue" class="data" x="626.1538461538462" y="15" width="6" height="530"></rect> 
    <circle cx="626.1538461538462" cy="(y1)" r="5" style="fill: #ffff00; stroke: #808080;"></circle> 
    <circle cx="626.1538461538462" cy="(y2)" r="5" style="fill: #ffff00; stroke: #808080;"></circle> 
    <circle cx="626.1538461538462" cy="(y3)" r="5" style="fill: #ffff00; stroke: #808080;"></circle> 
</g> 

我能想到的是遍歷的屬性和元素加入其中元素的唯一的事:

for (z=0; z< 3; ++z) 
{ 
    chart.append("svg:circle") 
    .data(items[z]['attributes']) 
    .style("fill", 'yellow') 
    .style("stroke", "gray") 
    .attr("cx", function(d, i) { return x(i+1); }) 
    .attr("cy", function(d, i) 
    { 
     console.log(d); 
     return bottom - 15; 
    }) 
    .attr("r", 5); 
} 

有沒有更好的方式來做到這一點?

回答

6

您可以創建一個嵌套的選擇,而不是循環:

chart.selectAll("svg:circle") 
    .data(function(item) { return item.attributes; }) 
    .enter() 
    .append("svg:circle") 
    .style("fill", 'yellow') 
    .style("stroke", "gray") 
    .attr("cx", function(d, i) { return x(i+1); }) 
    .attr("cy", function(d, i) 
    { 
     console.log(d); 
     return bottom - 15; 
    }) 
    .attr("r", 5); 

爲了保持cx同樣爲每個parentrect,你可以通過parent_idx通過

chart.selectAll("svg:circle") 
    .data(function(item, parent_idx) { 
     return item.attributes.map(function (attr_val) { 
       return { attr_val: attr_val, parent_idx: parent_idx }; 
      }); 
    }) 
    .enter() 
    .append("svg:circle") 
    .style("fill", 'yellow') 
    .style("stroke", "gray") 
    .attr("cx", function(d, i) { return x(d.parent_idx); }) 
    .attr("cy", function(d, i) 
    { 
     return y(d.attr_val); 
    }) 
    .attr("r", 5); 
+0

唯一我我有我的是圓應該在X軸上的同一行。基本上這些圓應該在同一行上(堆疊在矩形的頂部) – Paul

+0

@Paul更新了答案,同時保持每個「rect」的「cx」相同。 –

+0

這是完美的,效果很棒!謝謝! – Paul

3

您可以使用嵌套的選擇。主要選擇將創建小組,每個小組將有綁定到它的數據項。

var data = [ 
    {name: 'A', items: [1, 2]}, 
    {name: 'B', items: [2, 3, 4]} 
]; 

var cScale = d3.scale.category10() 
    .domain(d3.range(10)); 

var grp = svg.selectAll('g.main') 
    .data(data) 
    .enter() 
    .append('g') 
    .attr('class', 'main') 
    .attr('transform', function(d, i) { 
     return 'translate(0,' + i * 20 + ')'; 
    }); 

然後,您可以創建嵌套選擇,將訪問器函數傳遞給數據方法。我有一個矩形元素的例子,但用圓圈是一樣的:

grp.selectAll('rect') 
    .data(function(d) { return d.items; }) 
    .enter() 
    .append('rect') 
    .attr('x', function(d) { return 10 * d; }) 
    .attr('width', 8) 
    .attr('height', 10) 
    .attr('fill', function(d) { return cScale(d); }); 

您可能會發現文中的Nested Selections有用。我寫了一個小的jsfiddle太:http://jsfiddle.net/pnavarrc/h2YVd/