catspeake
这里的问题是关于transition.each: 你不能用它来包装几个transition.attr或transition.style方法的误解。事实上,它仅用于对该转换中的每个元素调用任意代码,就像selection.each.因此,当你做....each (function (d, i) { // complicated stuff with d I don't want to do twice d3.select(this) .attr("x", ((zz+i)%4) *20) .attr("y", ((zz+i)%4) *40)})...您只需更改 DOM 元素中的属性,该元素将立即跳转到新的x位置y,如预期的那样。换句话说,d3.select(this).attr(...您的代码中的那个是一个selection.attr,而不是一个transition.attr.您有多种选择(用于避免冗余的复杂计算)。如果你想坚持使用transition.each,你可以用它来创建一个新的局部变量,或者一个新的属性。为此,我们需要将对象作为数组中的数据元素,然后我们照常使用transition.attr:.each(function(d, i) { d.complexValue = ((zz + i) % 4) * 20;}).attr("x", function(d) { return d.complexValue;})//etc...这是一个演示:const sel = d3.select("svg") .selectAll(null) .data([{ color: "red" }, { color: "blue" }, { color: "green" }, { color: "yellow" }]) .enter() .append("rect") .attr("width", 30) .attr("height", 30) .attr("x", function(d, i) { return i * 20; }) .attr("y", function(d, i) { return i * 40; }) .style("fill", function(d) { return d.color; });let zz = 0;function each() { zz++; d3.selectAll("rect") .transition() .duration(1000) .each(function(d, i) { d.complexValue = ((zz + i) % 4) * 20; }) .attr("x", function(d) { return d.complexValue; }) .attr("y", function(d) { return d.complexValue; })};<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script><div id="demo"><svg width="360px"></svg></div><button onclick="each()">In an Each</button>