d3选择混淆exit()和remove()

时间:2017-12-04 23:23:32

标签: javascript d3.js data-visualization

所以我正在学习一些d3教程,并学习一些关于为什么事情按照他们的方式工作的事情,并且我遇到了一个特殊的选择实例,表现不尽如人意。所以我想知道是否有人可以向我解释这一点。

var sales = [
    { product: 'Hoodie',  count: 7 },
    { product: 'Jacket',  count: 6 },
    { product: 'Snuggie', count: 9 },
];

var rects = svg.selectAll('rect')
  .data(sales).enter();

var maxCount = d3.max(sales, function(d, i) {
    return d.count;
});
var x = d3.scaleLinear()
    .range([0, 300])
    .domain([0, maxCount]);
var y = d3.scaleBand()
    .rangeRound([0, 75])
    .domain(sales.map(function(d, i) {
        return d.product;
    }));

rects.append('rect')
    .attr('x', x(0))
    .attr('y', function(d, i) {
        return y(d.product);
    })
    .attr('height', y.bandwidth())
    .attr('width', function(d, i) {
        return x(d.count);
    });  

这一切都运作良好,生成3个与销售数据相对应的水平条,但这里是我看到模棱两可的地方:

sales.pop();

rects.data(sales).exit().remove();

最后一行应该从视觉中删除弹出的栏,但它不起作用。我认为必须有一些我缺少的d3选择,因为这确实有效:

d3.selectAll('rect').data(sales).exit().remove();

此外,当我突破第一个不起作用的时候,它似乎确实在退出时选择了正确的元素,但似乎并没有删除它。无论如何,如果有人能够解释这里发生的事情会非常有帮助,谢谢!

注意:使用d3 v4

2 个答案:

答案 0 :(得分:2)

这是您的rects选择:

var rects = svg.selectAll('rect')
    .data(sales).enter();

所以,当你这样做时:

rects.data(sales).exit().remove();

你实际上是这样做的:

svg.selectAll('rect')
    .data(sales)
    .enter()
    .data(sales)
    .exit()
    .remove();

因此,您绑定数据,调用enter,再次绑定数据并在所有内容之上调用exit!哇!

解决方案:只需创建一个定期的,老式的"更新"选择:

var rects = svg.selectAll('rect')
    .data(sales);

以下是您的代码的基本演示,2秒后调用exit



var svg = d3.select("svg")

var sales = [{
  product: 'Hoodie',
  count: 7
}, {
  product: 'Jacket',
  count: 6
}, {
  product: 'Snuggie',
  count: 9
}, ];

draw();

function draw() {

  var rects = svg.selectAll('rect')
    .data(sales);

  var maxCount = d3.max(sales, function(d, i) {
    return d.count;
  });
  var x = d3.scaleLinear()
    .range([0, 300])
    .domain([0, maxCount]);
  var y = d3.scaleBand()
    .rangeRound([0, 75])
    .domain(sales.map(function(d, i) {
      return d.product;
    }))
    .padding(.2);

  var rectsEnter = rects.enter().append('rect')
    .attr('x', x(0))
    .attr('y', function(d, i) {
      return y(d.product);
    })
    .attr('height', y.bandwidth())
    .attr('width', function(d, i) {
      return x(d.count);
    });

  rects.exit().remove();

}

d3.timeout(function() {
  sales.pop();
  draw()
}, 2000)

<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

rects已经是d3选择,因此您只需要rects.exit().remove()