Javascript 在D3中选择All仅工作一次

Javascript 在D3中选择All仅工作一次,javascript,d3.js,selection,Javascript,D3.js,Selection,这件事让我发疯了… 第一次调用时,refreshGraph()工作正常:显示我的图形。 在接下来的通话中,什么都不会发生。selectAll()按预期返回数组数组,但我的图形不变。 但是如果我使用select()而不是selectAll(),它会工作 最糟糕的是。。。如果我添加join.select(“.bar”)在join.selectAll(“.bar”)之前,它也可以工作 有人能解释为什么吗 我不理解这种行为。我完全理解select()和selectAll()将返回什么。对两个返回的子选择

这件事让我发疯了…
第一次调用时,refreshGraph()工作正常:显示我的图形。
在接下来的通话中,什么都不会发生。selectAll()按预期返回数组数组,但我的图形不变。
但是如果我使用select()而不是selectAll(),它会工作
最糟糕的是。。。如果我添加join.select(“.bar”)在join.selectAll(“.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();
var srcData=[4,8,15,16,23,42];
x=d3.scale.linear().domain([0,42])range([0,420]);
函数refreshGraph(){
join=d3.选择(“.chart”).selectAll(“.container”).data(srcData);
join.enter()
.append(“span”).attr(“类”、“容器”)
.append(“div”).attr(“class”、“bar”);
参加
.selectAll(“.bar”)//不起作用,但如果选择()而不是选择全部()则会起作用
.style(“宽度”,函数(d){
返回x(d)+“px”;
});
}
函数doChange(){
对于(var i=0;i
这里的问题是当数据绑定到子元素时

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

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

解决方法是每次调用
刷新数据时,将
.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");
该函数提供了一些技巧来帮助您:

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

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

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

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

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

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

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

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

希望它能帮助…

但我的refreshGraph()以d3.select(“.chart”).selectAll(“.container”).data(srcData)开头。这意味着每次调用函数时数据都绑定到.container元素。然后,join.enter()会添加缺少的节点,但尚未应用该样式。它应该由连接设置。selectAll(“.bar”)。。。这意味着“从.container(联接选择)中获取所有.bar类元素并应用此样式”。此外,它将与select()一起使用!为什么?.select()将父数据绑定到子数据。但这只是一个单一的元素选择,所以在这种情况下不起作用。