简体   繁体   English

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

[英]d3 selection confusion with exit() and remove()

So I'm working through some d3 tutorials and learning a bit about why things work the way they do, and I've run into a peculiar instance of selection not behaving as expected. 因此,我正在学习一些d3教程,并学习一些关于为什么事情按照他们的方式工作的方法,并且我遇到了一个特殊的选择实例,表现不尽如人意。 So I'm wondering if anyone can explain this to me. 所以我想知道是否有人可以向我解释这一点。

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

This all works good and fine, generates 3 horizontal bars that correspond to the data in sales, but here's where I'm seeing the ambiguity: 这一切都运行良好,生成3个与销售数据相对应的水平条,但这里是我看到歧义的地方:

sales.pop();

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

The last line is supposed to remove the bar that was popped, from the visual but it doesn't work. 最后一行应该从视觉中删除弹出的栏,但它不起作用。 I think that there must be something going on with the d3 selection that I'm missing, because this does work: 我认为必须有一些我缺少的d3选择,因为这确实有效:

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

Also when I break out the first one that doesn't work, it does appear to be selecting the correct element on exit, but just doesn't seem to be removing it. 另外,当我突破第一个不起作用的时候,它似乎确实在退出时选择了正确的元素,但似乎并没有删除它。 Anyway if anyone can explain what's going on here that would be very helpful, thanks! 无论如何,如果有人能够解释这里发生的事情会非常有帮助,谢谢!

Note: using d3 v4 注意:使用d3 v4

This is your rects selection: 这是您的rects的选择:

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

So, when you do this: 所以,当你这样做时:

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

You are effectively doing this: 你实际上是这样做的:

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

Thus, you are binding data, calling enter , binding data again and calling exit on top of all that! 因此,您正在绑定数据,再次调用enter ,绑定数据并在所有这些之上调用exit Wow! 哇!

Solution: just create a regular, old-fashioned "update" selection: 解决方案:只需创建一个常规的,老式的“更新”选择:

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

Here is a basic demo with your code, calling exit after 2 seconds: 这是一个带代码的基本演示,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> 

rects已经是d3选择,所以你只需要rects.exit().remove()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM