Javascript 条件转换的行为不符合预期

Javascript 条件转换的行为不符合预期,javascript,d3.js,svg,Javascript,D3.js,Svg,我想先转换绿色的圆圈,然后再转换红色的圆圈。转换绿色圆圈有效,但当我转换红色圆圈时,绿色圆圈会恢复到其原始位置。我怎样才能避免这种情况 d3.选择全部(“圆圈”) .transition().持续时间(1000) .attr(“cx”,函数(){ 如果(d3)选择(本) .style('fill')=“rgb(0,128,0)”){//绿色圆圈获得新的cx 返回150; }否则{ 返回d3.select(this.attr(“cx”)//红色圆圈保留cx } } ); d3.选择全部(“圆圈

我想先转换绿色的圆圈,然后再转换红色的圆圈。转换绿色圆圈有效,但当我转换红色圆圈时,绿色圆圈会恢复到其原始位置。我怎样才能避免这种情况


d3.选择全部(“圆圈”)
.transition().持续时间(1000)
.attr(“cx”,函数(){
如果(d3)选择(本)
.style('fill')=“rgb(0,128,0)”){//绿色圆圈获得新的cx
返回150;
}否则{
返回d3.select(this.attr(“cx”)//红色圆圈保留cx
} } );
d3.选择全部(“圆圈”)
.transition().持续时间(1000).延迟(1000)
.attr(“cx”,函数(){
如果(d3)选择(本)
.style('fill')=“rgb(255,0,0)”){//红色圆圈获得新的cx
返回200;
}否则{
返回d3.select(this).attr(“cx”)//绿色圆圈恢复为
//原始cx,未更改cx…为什么???
} } );

在转换过程中,attr和atttween之间有一个重要但微妙的区别。你之所以会遇到这个问题,是因为这种区别。虽然可能有更简单的方法解决这个问题,而不必担心它的机制,但我的答案将探讨你问题的原因,并提供一个与之相关的解决方案

首先,通过对您的转换进行一些修改,我们可以更清楚地看到问题:

var svg=d3.选择(“svg”);
d3.选择全部(“圆圈”)
.transition().持续时间(1000)
.on(“start”,function(){console.log(“start transition1”);})
.attr(“cx”,150);
d3.选择全部(“圆圈”)
.transition()
.延迟(1000)
.on(“start”,function(){return console.log(“start transition2”);})
.attr(“cx”,函数(){
console.log(“transition2cx值:”,d3.select(this.attr(“cx”));
返回d3.select(this.attr)(“cx”)
});

您试图做的不是惯用的D3,它将失败,原因已经解释过了。做每个人都做的事:
.on(“结束”等…

但是,出于好奇和完整性的考虑,您尝试做的(几乎)是可能的!只需在“第一次”转换中绑定数据并使用绑定的数据:

d3.selectAll("circle")
  .transition().duration(1000)
  .attr("cx", function(d) {
    if (d3.select(this)
      .style('fill') === "rgb(0, 128, 0)") {
      return d.x = 150;
    } else {
      return d.x = d3.select(this).attr("cx")
    }
  });

d3.selectAll("circle")
  .transition().duration(1000).delay(1000)
  .attr("cx", function(d) {
    if (d3.select(this)
      .style('fill') === "rgb(255, 0, 0)") {
      return 200;
    } else {
      return d.x
    }
  });
以下是演示:

d3.选择全部(“圆圈”)。每个(函数(){
d3.选择(本)基准面({
x:0
})
});
d3.选择全部(“圆圈”)
.transition().持续时间(1000)
.attr(“cx”,功能(d){
如果(d3)选择(本)
.style('fill')=“rgb(0,128,0)”){
返回d.x=150;
}否则{
返回d.x=d3。选择(this).attr(“cx”)
}
});
d3.选择全部(“圆圈”)
.transition().持续时间(1000).延迟(1000)
.attr(“cx”,功能(d){
如果(d3)选择(本)
.style('fill')=“rgb(255,0,0)”){
返回200;
}否则{
返回d.x
}
});


感谢您的详细解释。如果我理解正确,延迟不会改变同时计算转换的基本事实。是的,转换计时器会立即初始化,而不管延迟如何,因此两个转换的计时器将同时运行。@AndrewReid出于好奇,请检查我的答案。Ag绑定数据(或类或其他标识符和/或属性)的使用将避免问题。虽然我个人发现这种回答不太令人满意,因为它没有解释问题的根源,但这并不否定其他解决方案的有效性,我非常喜欢您使用转换来设置绑定数据。使用绑定数据确实是一种错误的解决方案,正如我在回答中试图阐明的:OP应该j我们必须像每个人一样使用
.on(“结束”
。然而,我喜欢展示一些事情是可能的,只是出于好奇……我喜欢这样,非常优雅。但我会听从你的建议,使用
on(“结束”…
,而不是试图打造我自己的道路。
d3.selectAll("circle")
  .transition().duration(1000)
  .attr("cx", function(d) {
    if (d3.select(this)
      .style('fill') === "rgb(0, 128, 0)") {
      return d.x = 150;
    } else {
      return d.x = d3.select(this).attr("cx")
    }
  });

d3.selectAll("circle")
  .transition().duration(1000).delay(1000)
  .attr("cx", function(d) {
    if (d3.select(this)
      .style('fill') === "rgb(255, 0, 0)") {
      return 200;
    } else {
      return d.x
    }
  });