2016-09-15 10 views
0

以下の最小限の例では、SVG要素が別の状態に移行し、元の状態に戻ります。元の属性をどのように除外して繰り返す必要はないでしょうか? selection.each()およびtransition.each()は予期せぬ混乱の結果をもたらしています。D3トランジションでの再利用のための属性の抽出

var circle = d3.select('svg').append('circle') 
 
    .attr('cx', 50) // this part should be factored out 
 
    .attr('cy', 130) 
 
    .attr('r', 25) 
 
    .attr('fill', 'blue'); 
 

 
circle.transition().duration(1000).delay(500) 
 
    .attr('cx', 200) 
 
    .attr('cy', 50) 
 
    .attr('r', 50) 
 
    .attr('fill', 'red') 
 
    .transition().duration(1000).delay(500) 
 
    .attr('cx', 50) // repeated 
 
    .attr('cy', 130) 
 
    .attr('r', 25) 
 
    .attr('fill', 'blue');
<!DOCTYPE html> 
 
<script src="https://d3js.org/d3.v4.min.js"></script> 
 

 
<svg width='300' height='170'> 
 
</svg>

答えて

0

call()代わりのeach()ました。私はそれが可能であることを知っていた!

function revert(selection) { 
 
    selection 
 
    .attr('cx', 50) 
 
    .attr('cy', 130) 
 
    .attr('r', 25) 
 
    .attr('fill','blue'); 
 
} 
 

 
var circle = d3.select('svg').append('circle') 
 
    .call(revert); 
 

 
circle.transition().duration(1000).delay(500) 
 
    .attr('cx', 200) 
 
    .attr('cy', 50) 
 
    .attr('r', 50) 
 
    .attr('fill','red') 
 
    .transition().duration(1000).delay(500) 
 
    .call(revert);
<!DOCTYPE html> 
 
<script src="https://d3js.org/d3.v4.min.js"></script> 
 

 
<svg width='300' height='170'> 
 
</svg>

0

一つの解決策は、D3のdata bindingの力を活用することであるかもしれません。後で元に戻す元の値と、要素が移行する値の両方を含む構成オブジェクトを定義できます。この情報をD3によって作成されたDOM要素にバインドすることで、後の呼び出しでアクセスすることができます。これらの構成オブジェクトは、次のようになります。

あなたが直接 selection.attrs()方法にそれらを渡すことにより、上記で定義された設定オブジェクトを使用することができます d3-selection-multiモジュールに投げる
var circle = [{ // D3 binds data contained in arrays 
    orig: {   // The original values 
    "cx": 50, 
    // ... 
    }, 
    trans: {  // The values to transition to 
    "cx": 200, 
    // ... 
    } 
}]; 

関数の戻り値が持つオブジェクトでなければなりません文字列値は、現在の要素の属性を設定するために使用されます。私は必要なもの

// Array of configuration objects 
 
var circle = [{ 
 
    orig: { 
 
    "cx": 50, 
 
    "cy": 130, 
 
    "r": 25, 
 
    "fill": "red" 
 
    }, 
 
    trans: { 
 
    "cx": 200, 
 
    "cy": 50, 
 
    "r": 50, 
 
    "fill": "blue" 
 
    } 
 
}]; 
 

 
// Create new elements by binding data and using data joins 
 
var circle = d3.select('svg').selectAll('circle') 
 
    .data(circle)        // Bind configuration objects to elements 
 
    .enter().append('circle') 
 
    .attrs(function(d) { return d.orig; }); // Use the original values 
 

 
circle.transition().duration(1000).delay(500) 
 
    .attrs(function(d) { return d.trans; }) // Transition to new values 
 
    .transition().duration(1000).delay(500) 
 
    .attrs(function(d) { return d.orig; }); // And transition back to original values
<!DOCTYPE html> 
 
<script src="https://d3js.org/d3.v4.min.js"></script> 
 
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script> 
 

 
<svg width='300' height='170'> 
 
</svg>

+0

感謝。私は実際にオブジェクトに属性を格納し、 'selection.attrs'を呼び出すことで繰り返しを避けましたが、いくつかの行のコードを保存するためにアドオン全体を読み込むことは不満でした。私は、 '.each()'がこのようなものを意図していると確信していましたが、間違っている可能性があります。 – bongbang

+0

さて、モジュールはちょうど1733バイト小さく、元のD3宇宙の一部です。私はコードをより鮮明に、より密でよりエレガントに見せるためにそれを含めました。もちろん、 '.attr()'メソッドの呼び出しだけでも同じことが達成できます。 – altocumulus

+0

一方、 '.each()'はこれにはあなたの友人ではありません。 – altocumulus

関連する問題