通过索引从d3js选择中获取一个元素

Ric*_*ich 20 d3.js

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

var data = [[0,0,2],[0,23,5],[2,12,5]];
circleSet = svg.selectAll()
             .data(data)
             .enter().append('circle');
Run Code Online (Sandbox Code Playgroud)

编辑:

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

ee2*_*Dev 22

操作一个元素最自然的方法是使用过滤器函数:

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');    
Run Code Online (Sandbox Code Playgroud)

请注意,根据您对其他元素的处理方式,您可以使用此方法的两种变体之一:

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

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

另请参阅在d3中过滤数据以绘制圆形或方形

另一种方法是使用selection.each方法:https://github.com/mbostock/d3/wiki/Selections#wiki-each 通过使用带有相应索引的if语句,您可以为一个创建一个块元件.例如

var data = [[0,0,2],[0,23,5],[2,12,5]];
var circleSet = svg.selectAll()
         .data(data)
         .enter()
         .append('circle')
         .each(function (d, i) {
            if (i === 1) {
              // put all your operations on the second element, e.g.
              d3.select(this).append('h1').text(i);    
            }
          });
Run Code Online (Sandbox Code Playgroud)


use*_*ca8 11

在d3 v4及更高版本中,您可以使用Selection.nodes().假设i是您想要的索引号:

d3.select(someSelection.nodes()[i])
Run Code Online (Sandbox Code Playgroud)

它是一个自然的单行,它可以说更具可读性:你显然只是i按顺序获取节点,作为D3选择.


看起来像它会比其它可供选择,其中包括通过与整个选择循环更有效.each().所以,你可能认为这是O(1),而其他选项是O(n).

不幸的是,Selection.nodes()本身包含一个each循环,所以它也是O(n)(并不是它在现实生活中很重要,除非你用数千个节点选择数千次):

var nodes = new Array(this.size()), i = -1;
this.each(function() { nodes[++i] = this; });
return nodes;
Run Code Online (Sandbox Code Playgroud)

但是,通过这种方式,您可以将循环与获取分开,这在效率是主要问题时非常有用.

例如,如果你想each()在选择A中循环并从选择B获取相同位置的项目,并且你想避免循环内循环,因为这些选择可能很大并且你多次调用,你可以构造它是这样的,它将是O(2n)而不是O(n ^ 2):

var selectionBArray = selectionB.nodes()

selectionA.each(function(d, i) {
  var iFromSelectionA = this
  var iFromSelectionB = d3.select(selectionBArray[i])
})
Run Code Online (Sandbox Code Playgroud)

...或者如果您使用箭头函数来保留this上下文:

var selectionBArray = selectionB.nodes()

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

您甚至可以(ab)使用Selection._groups,但我不建议使用这样的私有属性,因为如果D3更新重命名_groups属性,它将会中断,就像这个更新一样.


Lea*_*ple 6

使用预设函数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' };
Run Code Online (Sandbox Code Playgroud)

在本教程中,可以在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")
Run Code Online (Sandbox Code Playgroud)

最后,您可以使用.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); 
              )();   
            }
          });
Run Code Online (Sandbox Code Playgroud)