如何在d3中获取父选择?

时间:2017-01-20 07:34:08

标签: d3.js

创建此DOM:

<g>
    <rect></rect>
    <circle></circle>
</g>

来自.enter()选项,我试过了:

someUpdate.enter()
  .append('g')
    .attr('class', 'my-group')
    .append('rect')
      .attr('class', 'my-rect')
    // I'd like to get the .parent() here
    .append('cicle')
      .attr('class', 'my-circle')

.append('rect')将所选内容更改为rect后,此操作无效。

打破这个:

const update = someUpdate.enter()
  .append('g')
    .attr('class', 'my-group')

update
  .append('rect')
    .attr('class', 'my-rect')

update
  .append('cicle')
    .attr('class', 'my-circle')

作品。

但是,我想知道是否有更清洁的方式?

3 个答案:

答案 0 :(得分:4)

D3中没有用于遍历DOM的方法,例如jQuery的.parent()。因此,将其分解为单独的陈述的方式将是正确的方法。

另一方面,按照您的第一次建议,并非完全不可能。就在昨天,我向answer发布了一个"D3.js - what is selection.call() returning?",解释了selection.call()将如何准确返回调用它以允许方法链接的选择。牢记这一点,你可能会发生以下情况:

d3.select("svg").selectAll("g")
  .data([1])
  .enter().append('g')
    .call((parent) => parent.append('rect')
                        .attr("fill", "red")
                        .attr("width", 100).attr("height", 100))
    .call((parent) => parent.append('circle')
                        .attr("fill", "blue").attr("r", 50));
<script src="https://d3js.org/d3.v4.js"></script>
<svg></svg>

.call()调用的两个函数都将传递相同选择的先前输入的<g>元素,在这种情况下恰好是父元素。

虽然 可以这样做,但解决方案有其缺点。首先,对于任何经验丰富的D3开发人员来说,这看起来有点奇怪和尴尬,如果你想与他人分享或讨论你的代码,这可能会使事情变得复杂。其次,即使我将参数命名为parent,在这种特殊情况下,它仍然不等同于jQuery的.parent()方法。它将传入并返回与父选择或其他内容完全相同的选择。

答案 1 :(得分:3)

与其他人一致认为您的第二个代码段是正确的方式来执行您想要的我想要玩,如何:

d3.select("svg").selectAll("g")
    .data([1])
    .enter()
    .append('g')
    .each(function() {
        var p = d3.select(this);
        p.append('rect')
          .attr("fill", "red")
          .attr("width", 100).attr("height", 100);
        p.append('circle')
            .attr("fill", "blue").attr("r", 50);
    });
<script src="https://d3js.org/d3.v4.js"></script>
<svg></svg>

答案 2 :(得分:2)

@altocumulus在his answer中说:

  

虽然可以这样做,但解决方案有其缺点。首先,任何经验丰富的D3开发人员都会觉得有点奇怪和尴尬。

好吧,就像他一样,我不得不说OP的原始代码(将矩形和圆圈分别附加到组中)是标准方式,由大多数D3编码器应用。

但是,只是为了好玩并参加这个奇怪的比赛,这是另一种方法,使用不那么着名的第三个​​参数

d3.select("svg").selectAll("g")
    .data([1])
    .enter()
    .append('g')
    .attr("foo", function(d, i, p) {
        d3.select(p[0]).append('rect')
            .attr("fill", "red")
            .attr("width", 100).attr("height", 100);
        return null;
    })
    .attr("foo", function(d, i, p) {
        d3.select(p[0]).append('circle')
            .attr("fill", "blue").attr("r", 50);
        return null;
    });
<script src="https://d3js.org/d3.v4.js"></script>
<svg></svg>

我打赌这会赢得“尴尬代码”竞赛。