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

时间:2015-02-08 05:00:26

标签: d3.js

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

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

编辑:

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

3 个答案:

答案 0 :(得分:21)

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

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):使用过滤器排除而不是包含以便最后删除其他元素

另见Filter data in d3 to draw either circle or square

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

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);    
            }
          });

答案 1 :(得分:9)

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

d3.select(someSelection.nodes()[i])

这是一个自然的单行,它可以说更具可读性:你显然只是按顺序将节点放在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;

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

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

var selectionBArray = selectionB.nodes()

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

...或者如果您使用箭头功能来保存this上下文:

var selectionBArray = selectionB.nodes()

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

你甚至可以(ab)使用Selection._groups,但我不建议使用这样的私有属性,因为如果D3更新重命名为_groups属性,{{3} }。

答案 2 :(得分: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' };

在d3.js at this tutorial

中查找有关数组结构引用的更多信息

您还可以在分配课程时使用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); 
              )();   
            }
          });