2017-11-09 14 views
1

私はd3 v4を使って力のシミュレーショングラフを持っています。各ノードはいくつかのデータにバインドされており、各ノードの半径を決定するために使用します。基礎となるバインドされたデータが変更されたSVG要素のみを更新する

基本的なバインドされたデータは定期的に更新され、一部のノードでは変更され、他のノードでは変更されません。

バインドされたデータが変更されるDOM要素だけを選択して、グラフ上でこれらの要素を強調表示できるようにしたいと考えています。例えば

、最初に(forceSimulationノードにバインドされている)私のデータであることとします
data = [{id: 1, type: 0}, {id: 2, type: 1}] 、それは、その後に更新されます。
data = [{id: 1, type: 1}, {id: 2, type: 1}] 私はDOMを選択できるようにしたいのですが要素はid = 1に対応しているので、例えば色の変更を一時的に行うことができます。

更新選択にid = 1とid = 2の両方が含まれています - 以前のデータ値の内部マッピングを維持して比較することができましたが、これは非効率的です。

おかげで、 アダム単一データム属性がバインドされたデータが変更されたかどうかを確認するためにチェックすることができる場合

+1

')(' d3.local?ここから2番目の答えは、可能なモデルをデモ:https://stackoverflow.com/questions/23409250/compare-diff-new-data-with-previous-data-on-d3-js-update –

答えて

1

は、1つの方法は、selection.propertyを使用して、プロパティとtypeなどのカスタムプロパティとしてその属性を追跡することです。 、そして、

.append("circle") 
    .property("type",function(d) { return d.type; }); 

を更新する際、あなたはデータが一致するか、プロパティに一致していないかに基づいてフィルタリングすることもできます:データを追加するとき、あなたはかなり簡単にプロパティを定義することができ

circles.data(newdata) 
    .filter(function(d) { 
     return d.type != d3.select(this).property("type") 
    }) 

このフィルタは戻りますタイプを変更した要素。これで、新しいタイプを反映するためにプロパティを再割り当てし、それらのフィルタリングされたエレメントを遷移させることができます。

以下のスニペットでこれを実証する必要があります。データは1〜2の数字(青とオレンジ)で、プロパティの種類を設定するために使用されます。 svgをクリックしてデータを更新すると、データを変更するサークルだけが半径を一時的に変更し、新しいデータを反映するように色を変更します。

var svg = d3.select("body") 
 
    .append("svg") 
 
    .attr("width",400) 
 
    .attr("height",400); 
 
    
 
var circles = svg.selectAll("circle") 
 
    .data(data()) 
 
    .enter("circle") 
 
    .append("circle") 
 
    .attr("cy",function(d,i) { 
 
    return Math.floor(i/5) * 40 + 20; 
 
    }) 
 
    .attr("cx", function(d,i) { 
 
    return i%5 * 40 + 20 
 
    }) 
 
    .attr("r", 8) 
 
    .attr("fill",function(d) { return (d) ? "steelblue" : "orange"}) 
 
    .property("type",function(d) { return d; }); 
 
    
 
// update on click: 
 
svg.on("click", function() { 
 
    circles.data(data()) 
 
    .filter(function(d) { 
 
     return d != d3.select(this).property("type") // filter out unchanged data 
 
    }) 
 
    .property("type",function(d) { return d; }) // update to reflect new data 
 
    .transition() 
 
    .attr("r", 20) 
 
    .attr("fill","crimson") 
 
    .duration(500) 
 
    .transition() 
 
    .attr("fill",function(d) { return (d) ? "steelblue" : "orange" }) 
 
    .attr("r",8) 
 
    .duration(500); 
 
}) 
 
    
 

 
function data() { 
 
    var output = []; 
 
    d3.range(20).map(function(d) { 
 
    output.push(Math.round(Math.random())); 
 
    }) 
 
    return output; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>

関連する問題