d3js:如何select组的第n个元素?

d3js : How to select nth element of a group?

我创建了一个包含 9 个元素(圆圈)的组,例如:

// JS
var data=[ 1,2,3,4,5,6,7,8,9 ];
var svg = d3.select("body").append("svg");
var circles = svg.append("g").attr("id", "groupOfCircles")
    .selectAll("circle")
        .data(data)
    .enter().append("circle")
        .attr("cx", function(d){ return d*20;})
        .attr("cy", function(d){ return d*10;})
        .attr("r" , function(d){ return d;})
        .attr("fill","green");

//xml
<svg>
    <g id="groupOfCircles">
        <circle cx="20" cy="10" r="1" fill="green"></circle>
        <circle cx="40" cy="20" r="2" fill="green"></circle>
        <circle cx="60" cy="30" r="3" fill="green"></circle>
        <circle cx="80" cy="40" r="4" fill="green"></circle>
        <circle cx="100" cy="50" r="5" fill="green"></circle>
        <circle cx="120" cy="60" r="6" fill="green"></circle>
        <circle cx="140" cy="70" r="7" fill="green"></circle>
        <circle cx="160" cy="80" r="8" fill="green"></circle>
        <circle cx="180" cy="90" r="9" fill="green"></circle>
    </g>
</svg>

但是如何在不知道圈子的 id 或属性值的情况下 select 组的第 n 个元素(即:第 3 个圈子)groupOfCircles

稍后我将通过 for 循环遍历所有元素,并为每个元素着色一秒钟。


注意:我试过诸如:

  circles[3].attr("fill","red") // not working
  d3.select("#groupOfCircles:nth-child(3)").attr("fill","red")  // not working
  ..

或者select或者需要是circle:nth-child(3)——child表示元素是第n个子元素,而不是select元素的第n个子元素(参见 here)。

您还可以使用:

    // JS
    var data=[ 1,2,3,4,5,6,7,8,9 ];
    var svg = d3.select("body").append("svg");
    var circles = svg.append("g").attr("id", "groupOfCircles")
        .selectAll("circle")
            .data(data)
        .enter().append("circle")
            .attr("cx", function(d){ return d*20;})
            .attr("cy", function(d){ return d*10;})
            .attr("r" , function(d){ return d;})
            .attr("fill","green");
    
    d3.select("circle:nth-child(3)").attr("fill","red"); // <== CSS selector (DOM)
    d3.select(circles[0][4]).attr("fill","blue"); // <== D3 selector (node)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

如果你想在 d3 逻辑中做到这一点,匿名函数总是在数据旁边有一个索引参数:

my_selection.attr("fill",function(d,i) {return i%3==0?"red":"green";});

http://jsfiddle.net/risto/os5fj9m6/

您还可以使用 circles 数组来设置元素的属性:

d3.select(circles[3]).attr("fill","red");

// JS
var data=[ 1,2,3,4,5,6,7,8,9 ];
var svg = d3.select("body").append("svg");
var circles = svg.append("g").attr("id", "groupOfCircles")
    .selectAll("circle")
        .data(data)
    .enter().append("circle")
        .attr("cx", function(d){ return d*20;})
        .attr("cy", function(d){ return d*10;})
        .attr("r" , function(d){ return d;})
        .attr("fill","green");

var group = document.querySelector('#groupOfCircles');
var circleNodes = group.getElementsByTagName('circle');
d3.select(circleNodes[3]).attr("fill", "red");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

这里是另一个选项,使用函数作为选择器。

    circles.select(function (d,i) { return (i==3) ?  this : null;})
    .attr("fill", "red");

如果选择器是函数,它获取数据 (d) 和迭代器 (i) 作为参数。然后 returns 如果选中则为对象 (this),如果未选中则为 null。

d3 v4 现在支持使用 selection.nodes() 到 return 这个 [= 的所有元素的数组20=]选择。然后,我们可以通过d3.select(selection.nodes()[n改变第n个元素的属性]).attr(某物)

// JS
var data=[ 1,2,3,4,5,6,7,8,9 ];
var svg = d3.select("body").append("svg");
var circles = svg.append("g").attr("id", "groupOfCircles")
    .selectAll("circle")
        .data(data)
    .enter().append("circle")
        .attr("cx", function(d){ return d*20;})
        .attr("cy", function(d){ return d*10;})
        .attr("r" , function(d){ return d;})
        .attr("fill","green");

circleElements = circles.nodes(); // <== Get all circle elements
d3.select(circleElements[6]).attr("fill","red");
<script src="https://d3js.org/d3.v4.min.js"></script>