D3.js 按索引从d3js选择中获取一个元素

D3.js 按索引从d3js选择中获取一个元素,d3.js,D3.js,我基于3个元素的数组创建了一组d3js元素: var data = [[0,0,2],[0,23,5],[2,12,5]]; circleSet = svg.selectAll() .data(data) .enter().append('circle'); 编辑: 如何按索引选择第二个元素?使用预设函数I变量,该变量引用数组对象的索引 var data = [[0,0,2],[0,23,5],[2,12,5]]; circleSet = s

我基于3个元素的数组创建了一组d3js元素:

var data = [[0,0,2],[0,23,5],[2,12,5]];
circleSet = svg.selectAll()
             .data(data)
             .enter().append('circle');
编辑:


如何按索引选择第二个元素?

使用预设函数
I
变量,该变量引用数组对象的索引

var data = [[0,0,2],[0,23,5],[2,12,5]];
circleSet = svg.selectAll()
     .data(data)
     .enter()
     .append('circle')
     .attr('fill',function(d,i){i === 1 ? return 'red' : return 'black' };
在d3.js中找到有关数组结构引用的更多信息

分配类时,还可以利用
i
索引的计数对附加的每个元素进行编码

var data = [[0,0,2],[0,23,5],[2,12,5]];
    circleSet = svg.selectAll()
         .data(data)
         .enter()
         .append('circle')
         .attr("class",function(d,i){ return "yourclass item" + i })

var theSecondElement = d3.select(".item1")
最后,您可以使用.each方法和条件来针对特定元素

circleSet = svg.selectAll()
         .data(data)
         .enter()
         .append('circle')
         .each(function (d, i) {
            if (i === 1) {
              var that = this;
              (function textAdd() {
                 d3.select(that).append('h1').text(i); 
              )();   
            }
          });

仅操纵一个元素的最自然的方法是使用过滤器功能:

var data = [[0,0,2],[0,23,5],[2,12,5]];
var circleSet = svg.selectAll()
         .data(data)
         .enter()
         .append('circle');
var filteredCircleSet = circleSet
         .filter(function (d, i) { return i === 1;})
         // put all your operations on the second element, e.g.
         .append('h1').text('foo');    
请注意,根据您对其他元素所做的操作,您可能会使用此方法的两种变体之一:

  • 变量a):在数据函数中使用过滤器(减少数据和附加元素)

  • 变体b):使用过滤器排除而不是包括,以便在末尾移除其他元素

另见

另一种方法是使用选择。每种方法: 通过使用带有相应索引的if语句,可以为一个元素创建块。 例如


在D3V4及以上版本中,您可以使用。假设
i
是您想要的索引号:

d3.select(someSelection.nodes()[i])
这是一个自然的单行程序,而且可以说更具可读性:很明显,您只需要按顺序获取
i
处的节点,作为D3选择


它看起来比其他方法更有效,后者需要使用
.each()
循环整个选择。所以,你可能认为这是,而其他选项是O(n)

不幸的是,Selection.nodes()本身包含一个
每个
循环,因此它也是O(n)(在现实生活中这可能并不重要,除非你在有数千个节点的选择中调用了数千次):

然而,通过这种方式,您可以将循环与获取分开,如果效率是一个主要问题,这可能会很有用

例如,如果您希望循环选择A中的
each()
,并从选择B中获得相同位置的项,并且您希望避免循环中的循环,因为这些选择可能非常大,您可以多次调用它,您可以这样构造它,即O(2n)而不是O(n^2):

…或者如果您正在使用箭头函数来保留
上下文:

var selectionBArray = selectionB.nodes()

selectionA.each((d, i, nodes) => {
  var iFromSelectionA = d3.select(nodes[i])
  var iFromSelectionB = d3.select(selectionBArray[i])
})


您甚至可以(ab)使用
选择。_groups
,但我不建议使用这样的私有属性,因为如果D3更新重命名
_groups
属性,它会崩溃。

感谢您的回复。我编辑了我的答案,想问,我怎么能简单地选择第二个元素,这样我就可以用我想要的任何方式操纵它?已经给了您一个向上投票。您只需使用…enter().append('circle')。每个(函数(d,i){如果(i==1){//这里您将所有操作放在第二个元素上});例如,在块内放置d3。选择(this)。append('h1')。text(i);我已经用一种策略更新了我的答案,以解决您提出的问题。我只是添加了一种似乎对您的问题最自然的方法:只需使用筛选功能来选择您的元素。与其他答案相比,您可以绕过创建类或调用each函数。我已将此方法添加到我的答案中。祝您工作顺利!假设这些是SVG中唯一的圆,您可以执行
d3。选择(“圆:第n个子(2)”)
。在这样更改选择中间链时,请注意代码的可读性:例如,在第一个示例中,变量
circleSet
是单个项,而不是完整集。如果这样做,
var circleSet=d3.select()…append('something');var secondCircle=circleSet.filter(…)
可能更清晰。
var nodes = new Array(this.size()), i = -1;
this.each(function() { nodes[++i] = this; });
return nodes;
var selectionBArray = selectionB.nodes()

selectionA.each(function(d, i) {
  var iFromSelectionA = this
  var iFromSelectionB = d3.select(selectionBArray[i])
})
var selectionBArray = selectionB.nodes()

selectionA.each((d, i, nodes) => {
  var iFromSelectionA = d3.select(nodes[i])
  var iFromSelectionB = d3.select(selectionBArray[i])
})