2013-06-13 5 views
18

私は普及しているd3ライブラリのV3を使用していますが、基本的に3つのトランジションを続けておきます。最初のトランジションは終了セレクションに適用し、 3番目は入力選択になります。それらの選択肢の1つが空である場合、それぞれの遷移はスキップされるように連鎖されるべきです。私。出口選択がない場合、更新選択はすぐに開始されます。これまでのところ、このコードを用意しました(delay関数を使用しています)。d3:さまざまな選択肢で適切にトランジションを連鎖させるには

// 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を見ましたが、何が起こっているのか本当に理解していませんでした。

また、items.exit().transition().duration(TRANSITION_DURATION).remove()を書いているだけでは、itemsでは機能しません。おそらくSVG要素ではなくdivです。

答えて

30

です。ここには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は、入力要素を更新選択項目にマージし、それらを別々にしたいからです。詳細については、Update-only Transition exampleを参照してください。

また、transition.transitionchain 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

Iは、(デフォルトのパラメータを使用して遷移を導き出すのではなく)選択への遷移を適用するtransition.eachを使用することが広く知られている機能ではないが、後者は、もう少し慣用的であると仮定する。

+0

私が間違っている場合は私を修正してください。しかし、私はあなたのコードに 'delay()'メソッドを使って小さなエラーがあると思います。更新遷移がない場合(つまり要素が変更されない場合)、 'items.enter()。empty()'は 'false'に等しいので、elemensは終了し、' duration'ミリ秒は何も起こりません。開始する。しかし、視覚的な更新の遷移が起こっていない場合、私はenter transitionに続いてexit transition *に直ちに従います。このようにして、更新遷移を以下のように保存します: – wnstnsmth

+0

'var updatedItems = div.transition() .duration(継続時間) .delay(!div.exit()。空()* duration)'と.delay( !()!div.exit()。empty()+!div.enter()。empty())* duration) '.delay((!div.exit()。empty()+!updatedItems.empty *期間) '。このようにして、必要に応じて動作します。 – wnstnsmth