我正在尝试将this可堆叠条形图升级到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);
})
}
我觉得奇怪的是,这在D3 v3中完美无缺,为什么这不会在v4中运行?
答案 0 :(得分:6)
在d3 v3中,selectAll返回一个数组,在d3 v4中它返回一个对象。
来自v3 notes:
选择是元素数组 - 字面意思(可能不是字面意思......)。 D3将其他方法绑定到数组,以便您可以应用 运算符到选定的元素,例如设置属性 所有选定的元素。
选择不再使用原型链注入子类化Array; 它们现在是普通物体,提高了性能。内部字段 (selection._groups,selection._parents)是私有的;请使用 记录用于操纵选择的公共API。新的 selection.nodes方法生成选择中所有节点的数组。
如果要在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>
在此条形图的第3版中,在forEach循环中
`states.selectAll("rect").forEach(function(d,i) {`
d是一个节点数组(每个.g
中的矩形)。
但是,在v4中,d3选择不是数组,您不能以相同的方式使用forEach循环。但是你仍然可以使用selection.nodes()
获取其中的节点而不需要进行太多修改,而是让childNodes在v3版本中复制数组:
state.nodes().forEach(function(d, i) {
var nodes = d.childNodes;
这里我们遍历state
中的每个元素/节点并获取子rect
,作为数组返回。这是一个更新的fiddle。