javascript - D3 - 从 v3 升级到 v4 时,forEach 不是函数

标签 javascript d3.js foreach

我正在尝试升级 this可堆叠条形图到 v4。 除了一件事,一切正常。

当我过滤一个类别时,条形图不会落到 x 轴的起点。我收到一条错误消息:

state.selectAll(...).forEach is not a function

我已经尝试了多种方法,但我无法弄清楚这一点。 这是损坏的代码:

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

})
}

我觉得很奇怪,这在 D3 v3 中可以完美运行,为什么在 v4 中不能运行?

最佳答案

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

来自v3 notes :

Selections are arrays of elements—literally (maybe not literally...). D3 binds additional methods to the array so that you can apply operators to the selected elements, such as setting an attribute on all the selected elements.

哪里changes in v4包括:

Selections no longer subclass Array using prototype chain injection; they are now plain objects, improving performance. The internal fields (selection._groups, selection._parents) are private; please use the documented public API to manipulate selections. The new selection.nodes method generates an array of all nodes in a selection.

如果你想访问 v4 中的每个节点,请尝试:

selection.nodes().forEach( function(d,i) { ... })

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

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());
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>

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

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());  
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>


在这个条形图的 v3 中,在 forEach 循环中

`states.selectAll("rect").forEach(function(d,i) {`

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

但是,在 v4 中,d3 选择不是数组,您不能以相同的方式使用 forEach 循环。但是您仍然可以使用 selection.nodes() 获取其中的节点而无需进行太多修改,而不是让子节点复制 v3 版本中的数组:

state.nodes().forEach(function(d, i) {
            var nodes = d.childNodes;

在这里,我们遍历 state 中的每个元素/节点并获取子 rect,以数组形式返回。这是更新的 fiddle .

关于javascript - D3 - 从 v3 升级到 v4 时,forEach 不是函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47078756/

相关文章:

PHP Laravel 中断 foreach 循环 2 次

javascript - jQuery on click 不适用于 iPhone(触摸设备)

javascript - 将简单数组转换为对象

javascript - 在 D3 V4 中添加自定义画笔 handle ?

javascript - 如何使用reduce()来模仿forEach()的功能?

c# - foreach 循环迭代中的多个异步/等待调用

javascript - 我该如何解决这个 Javascript/CSS 问题?

javascript - Angular 绑定(bind)不会更新

javascript - 尝试实现 svg :clipPath but end up with almost a blank screen

javascript - 如何在浏览器窗口底部以直线绘制圆数组