d3: How to properly chain transitions on different selections

为君一笑 提交于 2019-11-28 04:44:09

Sure. Here are two ways.

First, you could use an explicit delay, which you then compute using selection.empty to skip empty transitions. (This is only a minor modification of what you have already.)

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

http://bl.ocks.org/mbostock/5779682

One tricky thing here is that you have to create the transition on the updating elements before you create the transition on the entering elements; that’s because enter.append merges entering elements into the update selection, and you want to keep them separate; see the Update-only Transition example for details.

Alternatively, you could use transition.transition to chain transitions, and transition.each to apply these chained transitions to existing selections. Within the context of transition.each, selection.transition inherits the existing transition rather than creating a new one.

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

http://bl.ocks.org/mbostock/5779690

I suppose the latter is a bit more idiomatic, although using transition.each to apply transitions to selections (rather than derive transitions with default parameters) isn’t a widely-known feature.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!