d3:如何正确链接不同选择的转换 [英] d3: How to properly chain transitions on different selections

查看:31
本文介绍了d3:如何正确链接不同选择的转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用流行的 d3 库的 V3 并且基本上想要有三个过渡,然后依次:第一个过渡应用于退出选择,第二个应用于更新选择,第三个应用于进入选择.它们应该以这样的方式链接,当其中一个选择为空时,跳过其各自的转换.IE.当没有退出选择时,更新选择应立即开始.到目前为止,我已经想出了这段代码(使用 delay 函数).

I am using V3 of the popular d3 library and basically want to have three transitions, followed by each other: The first transition should apply to the exit selection, the second to the update selection and the third to the enter selection. They should be chained in such a manner that when one of the selections is empty, its respective transition is skipped. I.e. when there is no exit selection, the update selection should start immediately. So far, I have come up with this code (using the delay function).

// DATA JOIN
var items = d3.select('#data').selectAll('.item');
items = items.data(data, function(d){ 
    return d.twitter_screenname;
});


// EXIT
items.exit().transition().duration(TRANSITION_DURATION).style('opacity', 0).remove();

// UPDATE
// Divs bewegen
items.transition().duration(TRANSITION_DURATION).delay(TRANSITION_DURATION * 1)
    .style('left', function(d, i) {
        return positions[i].left + "px";
    }).style('top', function(d, i) {
        return positions[i].top + "px";
    });

// ENTER
// Divs hinzufügen
var div = items.enter().append('div')
    .attr('class', 'item')
    .style('left', function(d, i) {
        return positions[i].left + "px";
    }).style('top', function(d, i) {
        return positions[i].top + "px";
    });

 div.style('opacity', 0)
    .transition().duration(TRANSITION_DURATION).delay(TRANSITION_DURATION * 2)
    .style('opacity', 1);

首先它不允许跳过"转换,其次我认为有比 delay 更好的方法.我看过 http://bl.ocks.org/mbostock/3903818 但我看过不太明白发生了什么.

First of all it doesn't allow to "skip" transitions and secondly I think there is a better way than delay. I've looked at http://bl.ocks.org/mbostock/3903818 but I did not really understand what is happening.

此外,不知何故,仅编写 items.exit().transition().duration(TRANSITION_DURATION).remove() 不适用于 items,可能是因为它们不是 SVG 元素,而是 divs.

Also, somehow just writing items.exit().transition().duration(TRANSITION_DURATION).remove() does not work with the items, probably because they are not SVG elements but divs.

推荐答案

好的.这里有两种方法.

Sure. Here are two ways.

首先,您可以使用显式延迟,然后使用selection.empty 跳过空过渡.(这只是对您已有内容的微小修改.)

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

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

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.

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

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

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

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.

这篇关于d3:如何正确链接不同选择的转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆