【问题标题】:Confused about data joins, select and selectAll对数据连接、选择和全选感到困惑
【发布时间】:2013-05-14 02:25:14
【问题描述】:

我对数据连接感到困惑。

我有一个名为 gEnter 的进入组元素,我将其附加到该元素

gEnter.append("g").attr("class", "dataLabels");

dataLabels 是我将制作的每个数据标签的容器元素。

g 是原始组元素的更新选择。我像这样绑定我的数据:

var dataLabels = g.select(".dataLabels")
    .selectAll(".dataLabel")
    .data(function(d) {return d;});

其中d 来自父g 元素。对于每个新数据点,我附加一个.dataLabel,并为其提供一个距轴 30 像素的起始位置:

var dataLabelsEnter = dataLabels.enter()
    .append("g")
    .attr("class", "dataLabel")
    .attr("transform", function(d, i) { return "translate("+ (xScale(d.category) + (xScale.rangeBand() / 2)) +","+(yScale(0) - 30)+")"; });

每个.dataLabel 本身就是两个text 元素的容器,因此我将它们附加到每个新数据点:

dataLabelsEnter.append("text")
    .attr("class", "category")
    .attr("text-anchor", "middle")
    .style("font-weight", function(d, i) {
        return (d.category == 'Total')
            ? 'bold'
            : 'normal';
    })
    .text(function(d) {return d.category;});

dataLabelsEnter.append("text")
    .attr("class", "value")
    .attr("text-anchor", "middle")
    .attr("transform", "translate(0,20)")
    .style("font-weight", "bold")
    .style("fill", function(d, i) { 
        return (d.count >= 0)
            ? '#1f77b4'
            : '#BB1A03';
    })
    .text(function(d) {
        var accounting = d3.format(",");
        return (d.count >= 0)
            ? '+$' + accounting(d.count)
            : '-$' + accounting(-d.count);
    });

然后我转到我的更新代码,事情变得有趣了。首先,我更新容器.dataLabel 元素的位置。这很好用:

dataLabels
    .transition()
    .duration(duration)
    .attr("transform", function(d, i) {return "translate("+ (xScale(d.category) + (xScale.rangeBand() / 2)) +","+( yScale(d3.max([d.count,0])) - 30)+")"; });

现在我想更新标签的值。我试试这个:

dataLabels
    .selectAll(".value")
    .text(function(d, i) {
        var accounting = d3.format(",");
        // return d.count;
        return (d.count >= 0)
            ? '+$' + accounting(d.count)
            : '-$' + accounting(-d.count);
    });

但它不起作用。我尝试使用.data(function(d){return d;}) 重新绑定数据,但无济于事。不管我做什么,即使数据更新了,这里还是和最初的平局一样。但是,如果我切换到

dataLabels
    .select(".value")
    .text(function(d, i) {
        var accounting = d3.format(",");
        // return d.count;
        return (d.count >= 0)
            ? '+$' + accounting(d.count)
            : '-$' + accounting(-d.count);
    });

它有效。

谁能解释为什么后一个选择获得更新的数据,但前一个选择没有?我读过Mike Bostock's recent article on selections,但还是有点困惑。我相信这与文章中的这句话有关:

只有 selectAll 有关于分组的特殊行为; select 保留现有的分组。

也许 selectAll 正在从每个 .dataLabel 元素创建新组,但数据没有绑定到它们?我只是不确定。

【问题讨论】:

    标签: d3.js


    【解决方案1】:

    不同之处在于 selection.select 将数据从父级传播到子级,而 selection.selectAll 则不会。再次阅读您在Non-Grouping Operations 部分引用的段落:

    只有 selectAll 有关于分组的特殊行为; select 保留现有的分组。 select 方法有所不同,因为新选择中的每个元素都对应旧选择中的每个元素。因此,select 还会将数据从父级传播到子级,而 selectAll 不会(因此需要数据连接)!

    因此,当您在 dataLabels 上进行数据连接时,您已经更新了父元素上的数据。但是当您调用 dataLabels.selectAll(".value") 时,它不会传播数据,因此您获得的是 old 子数据。如果您切换到dataLabels.select(".value"),它会将数据传播给选定的子节点,因此您会再次获得新数据。

    您也可以使用 selection.data 传播数据,但由于此处每个标签都有一个值元素,因此使用 selection.select 更容易。

    (另外,您可能需要指定key function。)

    【讨论】:

    • 它刚刚点击。当然.selectAll 不能传播父数据——新元素(可能)比数据点多。太好了,谢谢! (感谢您所做的所有令人难以置信的工作!)
    猜你喜欢
    • 2014-01-04
    • 2010-09-14
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 2013-01-17
    • 2011-03-26
    相关资源
    最近更新 更多