21

私は人気のある d3 ライブラリの V3 を使用しており、基本的に 3 つのトランジションが必要です。最初のトランジションは終了選択に適用され、2 番目は更新選択に適用され、3 番目は開始選択に適用されます。選択の 1 つが空の場合、それぞれのトランジションがスキップされるようにチェーンする必要があります。つまり、終了選択がない場合、更新選択はすぐに開始する必要があります。delayこれまでのところ、(関数を使用して)このコードを思いつきました。

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

まず第一に、トランジションを「スキップ」することはできません。第二に、より良い方法があると思いますdelayhttp://bl.ocks.org/mbostock/3903818を見ましたが、何が起こっているのかよくわかりませんでした。

また、SVG 要素ではなくitems.exit().transition().duration(TRANSITION_DURATION).remove()s .itemsdiv

4

1 に答える 1

33

もちろん。ここに2つの方法があります。

まず、明示的なdelayを使用できます。次に、 selection.emptyを使用して計算し、空の遷移をスキップします。(これは、既にあるものを少し変更しただけです。)

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が入力要素を更新選択にマージし、それらを別々に保持したいためです。詳細については、更新のみの遷移の例を参照してください。

または、 transition.transition を使用してtransitionsチェーン化し、transition.eachを使用してこれらのチェーン化されたトランジションを既存の選択に適用することもできます。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);
});

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

後者はもう少し慣用的だと思いますが、transition.each を使用して (既定のパラメーターで遷移を派生させるのではなく) 選択に遷移を適用することは、広く知られている機能ではありません。

于 2013-06-14T05:43:25.690 に答える