繁体   English   中英

selectAll仅在D3中工作一次

[英]selectAll works only once in D3

我生气这个...
第一次调用时,refreshGraph()工作正常:显示我的图表。
接下来的电话,没有任何反应。 selectAll()按预期返回数组数组, 但我的图形不会更改
但是......如果我使用select()而不是selectAll(),它就可以了!
最糟糕的...如果我在join.selectAll(“。bar”)之前添加join.select(“。bar”)它也可以!

谁能解释我为什么?

我不明白这种行为。 我完全理解select()和selectAll()应该返回什么。 在两个返回的子选择上调用style()应该给出相同的结果,因为数据是相同的,即使按组使用selectAll进行组织,并使用select进行平展。 我对吗 ?

var srcData = [4, 8, 15, 16, 23, 42];

x = d3.scale.linear().domain([0, 42]).range([0, 420]);

function refreshGraph() {

    join = d3.select(".chart").selectAll(".container").data(srcData);

    join.enter()
    .append("span").attr("class","container")
    .append("div").attr("class","bar");

    join
    .selectAll(".bar") // wont work, but will if select() instead of selectAll()
    .style("width", function(d) { 
        return x(d) + "px";
    });
}

function doChange() {
    for (var i = 0; i < srcData.length; i++) {
        srcData[i] /= 2;
    }
    refreshGraph();
}

refreshGraph();

这里的问题是数据绑定子元素的时间。

  • 当您调用.selectAll('.container').data(srcData).container元素的初始数据将被绑定,并在每次再次调用时重新绑定新数据。

  • .bar元素的数据在创建时被绑定,当它们被附加到.container元素时,但在将新数据绑定到.container不会反弹。

修复是每次调用refreshData时强制将.bar数据重新绑定到其父数据:

join
    .selectAll(".bar")
    .data(function(d) { return [d]; })
    .style("width", function(d) { 
        return x(d) + "px";
    });

经过几个小时的阅读文档,并进入D3代码,我终于明白了。 我结合了几个案例,这让我陷入困境。 那么,这是关于什么的?

 join = d3.select(".chart").selectAll(".container").data(srcData);
 join.enter()
.append("span").attr("class","container")
.append("div").attr("class","bar");

append()函数可以帮助您:

将具有指定名称的新元素追加为当前选择中每个元素的最后一个子元素,并返回包含附加元素的新选择。 每个新元素都以与选择子选择相同的方式继承当前元素的数据(如果有)。

但是...... 继承词是误导性的。 您必须阅读: 每个新元素都从当前元素接收数据的副本

正如D3的工作方式,没有魔法绑定。 与每次要反映值更改时重新绑定数据的方式相同,您必须在正确的节点中设置数据。 append()函数为你完成了这个工作,select()函数也可以这样做,但是selectAll()没有。

对于当前选择中的每个元素,选择与指定选择器字符串匹配的后代元素。 ...子选择不继承当前选择的数据;

在我的问题代码中,在第一次调用时,数据通过append()从.container复制到.bar元素。 由于数据的数量没有变化(没有新值/没有更少的值),后续调用绕过append()函数(enter()部分为空)并且selectAll()将获得正确的节点(.bar分类)仍然有以前的数据版本。 调用style()时,这不是应用的新数据。

当然,使用select()使它工作,因为它将数据从祖先复制到子选择元素。

nrabinowitz给出了一个正确的答案:如果你绝对想要使用selectAll,你必须使用一个函数来检索分组节点的数据。

selectAll()doc说: 返回的选择当前选择中的祖先节点分组 ...如果数据值被指定为函数,则将使用祖先节点的数据d和组索引i调用此函数确定子选择的数据绑定。

希望它会有所帮助......

暂无
暂无

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

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