D3 - 从v3升级到v4时,forEach不是一个功能

kev*_*fee 7 javascript foreach d3.js

我正在尝试将此可堆叠条形图升级到v4.除了一件事,一切都有效.

当我过滤一个类别时,条形不会下降到x轴的起点.我收到一个错误,上面写着:

state.selectAll(...).forEach不是一个函数

我尝试了很多东西,但我无法想出这个.这是破碎的代码:

function plotSingle(d) {

class_keep = d.id.split("id").pop();
idx = legendClassArray.indexOf(class_keep);

//erase all but selected bars by setting opacity to 0
d3.selectAll(".bars:not(.class" + class_keep + ")")
    .transition()
    .duration(1000)
    .attr("width", 0) // use because svg has no zindex to hide bars so can't select visible bar underneath
    .style("opacity", 0);

//lower the bars to start on x-axis
state.selectAll("rect").forEach(function(d, i) {

    //get height and y posn of base bar and selected bar
    h_keep = d3.select(d[idx]).attr("height");
    y_keep = d3.select(d[idx]).attr("y");

    h_base = d3.select(d[0]).attr("height");
    y_base = d3.select(d[0]).attr("y");

    h_shift = h_keep - h_base;
    y_new = y_base - h_shift;

    //reposition selected bars
    d3.select(d[idx])
        .transition()
        .ease("bounce")
        .duration(1000)
        .delay(750)
        .attr("y", y_new);

})
}
Run Code Online (Sandbox Code Playgroud)

我觉得奇怪的是,这在D3 v3中完美无缺,为什么这不能在v4中运行?

And*_*eid 6

在d3 v3中,selectAll返回一个数组,在d3 v4中它返回一个对象.

v3笔记:

选择是元素数组 - 字面意思(可能不是字面意思......).D3将其他方法绑定到数组,以便您可以将运算符应用于所选元素,例如在所有选定元素上设置属性.

凡为V4中的变化包括:

选择不再使用原型链注入子类化Array; 它们现在是普通物体,提高了性能.内部字段(selection._groups,selection._parents)是私有的; 请使用记录的公共API来操作选择.新的selection.nodes方法生成选择中所有节点的数组.

如果要在v4中访问每个节点,请尝试:

selection.nodes().forEach( function(d,i) { ... })
Run Code Online (Sandbox Code Playgroud)

但是,这只是节点,以获取选择每个节点所需的数据:

var data = [0,1,2];

var svg = d3.select("body").append("svg")
  .attr("width",500)
  .attr("height",200)

var circles = svg.selectAll("circle")
  .data(data)
  .enter()
  .append("circle")
  .attr("cx", function(d,i) { return i * 20 + 50 })
  .attr("cy", 50)
  .attr("r", 4);
  
  
circles.nodes().forEach(function(d,i) {
    console.log(d3.select(d).data());
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

但是,如果您需要数据或修改选择属性,则可以更容易地使用selection.each().d3.each遍历d3选择本身的每个元素,并允许您为选择中的每个元素调用一个函数(请参阅此处的 API文档):

var data = [0,1,2];

var svg = d3.select("body").append("svg")
  .attr("width",500)
  .attr("height",200)

var circles = svg.selectAll("circle")
  .data(data)
  .enter()
  .append("circle")
  .attr("cx", function(d,i) { return i * 20 + 50 })
  .attr("cy", 50)
  .attr("r", 4);
  

  
circles.each( function() {
  console.log(d3.select(this).data());  
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
Run Code Online (Sandbox Code Playgroud)


在此条形图的第3版中,在forEach循环中

`states.selectAll("rect").forEach(function(d,i) {`
Run Code Online (Sandbox Code Playgroud)

d是节点数组(每个节点中的矩形.g).

但是,在v4中,d3选择不是数组,您不能以相同的方式使用forEach循环.但是你仍然可以在没有太多修改的情况下获取其中的节点,selection.nodes()而不是让childNodes在v3版本中复制数组:

state.nodes().forEach(function(d, i) {
            var nodes = d.childNodes;
Run Code Online (Sandbox Code Playgroud)

在这里,我们遍历每个元素/节点state并获取子节点rect,作为数组返回.这是一个更新的小提琴.