Animation d3:如何正确地在不同选择上链接过渡

Animation d3:如何正确地在不同选择上链接过渡,animation,d3.js,transition,Animation,D3.js,Transition,我使用的是流行的d3库的V3,基本上希望有三个转换,然后依次进行:第一个转换应用于退出选择,第二个转换应用于更新选择,第三个转换应用于进入选择。它们应该以这样的方式链接:当其中一个选择为空时,将跳过其各自的转换。即,当没有退出选择时,更新选择应立即启动。到目前为止,我已经找到了这个代码(使用delay函数) 首先,它不允许“跳过”转换,其次,我认为有一种比延迟更好的方法。我已经看过了,但我并不真正理解发生了什么 另外,仅仅编写items.exit().transition().duration(

我使用的是流行的d3库的V3,基本上希望有三个转换,然后依次进行:第一个转换应用于退出选择,第二个转换应用于更新选择,第三个转换应用于进入选择。它们应该以这样的方式链接:当其中一个选择为空时,将跳过其各自的转换。即,当没有退出选择时,更新选择应立即启动。到目前为止,我已经找到了这个代码(使用
delay
函数)

首先,它不允许“跳过”转换,其次,我认为有一种比延迟更好的方法。我已经看过了,但我并不真正理解发生了什么


另外,仅仅编写
items.exit().transition().duration(transition\u duration).remove()
并不适用于
项,可能是因为它们不是SVG元素,而是
div
s

当然。这里有两种方法

首先,您可以使用显式转换,然后使用显式转换跳过空转换进行计算。(这只是对已有内容的一个小修改。)

这里有一件棘手的事情,在对输入元素创建转换之前,必须在更新元素上创建转换;这是因为将输入元素合并到更新选择中,并且您希望将它们分开;有关详细信息,请参阅

或者,您可以使用和将这些链接转换应用于现有选择。在transition.each的上下文中,selection.transition继承现有的转换,而不是创建新的转换

var div = d3.select("body").selectAll("div")
    .data(["enter", "update"], function(d) { return d || this.textContent; });

// 1. exit
var exitTransition = d3.transition().duration(750).each(function() {
  div.exit()
      .style("background", "red")
    .transition()
      .style("opacity", 0)
      .remove();
});

// 2. update
var updateTransition = exitTransition.transition().each(function() {
  div.transition()
      .style("background", "orange");
});

// 3. enter
var enterTransition = updateTransition.transition().each(function() {
  div.enter().append("div")
      .text(function(d) { return d; })
      .style("opacity", 0)
    .transition()
      .style("background", "green")
      .style("opacity", 1);
});


我认为后者更为惯用,尽管使用transition.each将转换应用于选择(而不是使用默认参数派生转换)并不是广为人知的功能。

如果我错了,请纠正我,但我认为使用
delay()
-方法的代码中有一个小错误。当没有更新转换(即,没有元素改变位置)时,
items.enter().empty()
仍然等于
false
,因此元素退出,然后在
持续时间
毫秒内什么也不发生,然后开始输入转换。但是,如果没有发生视觉更新转换,我希望退出转换之后紧接着进入转换。因此,我将更新转换保存如下:
var updateItems=div.transition().duration(duration).delay(!div.exit().empty()*duration)
并更改
.delay(!div.exit().empty()+!div.enter().empty())*duration)
。这样它就可以按需要工作。
var div = d3.select("body").selectAll("div")
    .data(["enter", "update"], function(d) { return d || this.textContent; });

// 2. update
div.transition()
    .duration(duration)
    .delay(!div.exit().empty() * duration)
    .style("background", "orange");

// 3. enter
div.enter().append("div")
    .text(function(d) { return d; })
    .style("opacity", 0)
  .transition()
    .duration(duration)
    .delay((!div.exit().empty() + !div.enter().empty()) * duration)
    .style("background", "green")
    .style("opacity", 1);

// 1. exit
div.exit()
    .style("background", "red")
  .transition()
    .duration(duration)
    .style("opacity", 0)
    .remove();
var div = d3.select("body").selectAll("div")
    .data(["enter", "update"], function(d) { return d || this.textContent; });

// 1. exit
var exitTransition = d3.transition().duration(750).each(function() {
  div.exit()
      .style("background", "red")
    .transition()
      .style("opacity", 0)
      .remove();
});

// 2. update
var updateTransition = exitTransition.transition().each(function() {
  div.transition()
      .style("background", "orange");
});

// 3. enter
var enterTransition = updateTransition.transition().each(function() {
  div.enter().append("div")
      .text(function(d) { return d; })
      .style("opacity", 0)
    .transition()
      .style("background", "green")
      .style("opacity", 1);
});