2017-01-13 8 views
2

ためのD3 v4の更新-パターン:次のレイアウトを考えるグループ

<g> 
    ... // many nodes 
    <g> 
     <circle></circle> 
     <text></text> 
    </g> 
    ... 
</g> 

はどのように正しい更新パターンは、D3のv4の中のように見えるのでしょうか? 私は、マージにパラメータとして使用するために何を持っているか、どのくらいの頻度私は(唯一のノードノード+円+テキストに?)マージを呼び出す必要があります

私はフィドルに取り組んで例を作成した(?):https://jsfiddle.net/cvvfsg97/6/

コード:

function update(items) { 
    node = nodeLayer.selectAll(".node") 
    .data(items, function(d) { return d.id; }) 

    node = node.enter() // insert 
    .append("g") 
    .attr("class", "node"); 

    node.append("circle") // insert 
    .attr("r", 2.5) 
    .attr('class', 'circle') 
    .merge(nodeLayer.selectAll('.node > circle')) // is this correct?! // merge 
    .attr('fill', 'red') // just for testing purposes 
    .exit().remove(); // exit 

    node.append("text") // insert 
     .attr("dy", 3) 
     .text(function(d) { return d.name; }) 
     .merge(nodeLayer.selectAll('.node > text')) // is this correct?! // merge 
     .attr('fill', 'green') // just for testing purposes 
     .exit().remove(); 

    node.merge(nodeLayer.selectAll('.node')) // is this correct?! // merge 
    .attr('class', 'anotherClass') 
    .exit().remove(); // does not work // exit 
} 

誰かが、)(マージ)(入力の使用方法の面でグループでexit()をいくつかの明快さを持ってもらえますか?

私は潜在的にすべての要素のすべての段階で変更を行うのが好きです。


更新:私は、私がリンクまたはforce-レイアウトを必要としない例を簡素化。私の質問は、武力についてではなく、更新パターンについてだけです。更新されたjsfiddleにはforce-layoutはありません。

+0

は、あなたが見てきたhttps://bl.ocks.org/mbostock/3808218 ? merged – softwarenewbie7331

+1

@ Frame91で更新されました。ここでは2つの異なる質問があることに気付きました.1つは更新パターンそのものに関するもので、もう1つは力の更新方法に関するものです。それらは実質的に異なる質問である。今の問題は、あなたの一般的な質問(更新パターン)に対処するすべての回答が、あなたが現在持っている2つの回答のように、力の問題に正しく対処できないということです。したがって、この質問を削除し、テキストとサークルを含むグループの更新パターンを作成する方法については、別の記事を投稿することをお勧めします(簡単に回答できます)。 –

+1

私は力のレイアウトに興味がありません。私は更新パターンだけを気にします。私はちょうどjsfiddleの既存の例を使用しました。混乱して申し訳ありません;) – Frame91

答えて

2

あなたはパターンを複雑にしています。ここにあなたの更新機能が正しく書かれています:ここで

function update(items) { 

    var node = nodeLayer.selectAll(".node") // bind the data, this is update 
    .data(items, function(d) { 
     return d.id; 
    }); 

    node.exit().remove(); // exit, remove the g 

    nodeEnter = node.enter() // enter, append the g 
    .append("g") 
    .attr("class", "node"); 

    nodeEnter.append("circle") // enter, append the circle on the g 
    .attr("r", 2.5) 
    .attr('class', 'circle') 
    .attr('fill', 'red'); 

    nodeEnter.append("text") // enter, append the text on the g 
    .attr("dy", 3) 
    .text(function(d) { 
     return d.name; 
    }) 
    .attr('fill', 'green'); 

    node = nodeEnter.merge(node); // enter + update on the g 

    node.attr('transform', function(d){ // enter + update, position the g 
    return 'translate(' + d.x + ',' + d.y + ')'; 
    }); 

    node.select("text") // enter + update on subselection 
    .text(function(d) { 
     return d.name; 
    }); 

} 

は、それが複数の呼び出しで実行されている:

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script> 
 
</head> 
 

 
<body> 
 
    <script> 
 
    
 
    var nodeLayer = d3.select('body') 
 
     .append('svg') 
 
     .attr('width',500) 
 
     .attr('height',500); 
 
     
 
    update([ 
 
     { 
 
     id: 1, 
 
     name: 'A', 
 
     x: Math.random() * 500, 
 
     y: Math.random() * 500 
 
     },{ 
 
     id: 2, 
 
     name: 'B', 
 
     x: Math.random() * 500, 
 
     y: Math.random() * 500 
 
     },{ 
 
     id: 3, 
 
     name: 'C', 
 
     x: Math.random() * 500, 
 
     y: Math.random() * 500 
 
     } 
 
    ]); 
 
    
 
    setTimeout(function(){ 
 
     update([ 
 
     { 
 
      id: 1, 
 
      name: 'A', 
 
      x: Math.random() * 500, 
 
      y: Math.random() * 500 
 
     },{ 
 
      id: 4, 
 
      name: 'This is a new name...', 
 
      x: Math.random() * 500, 
 
      y: Math.random() * 500 
 
     },{ 
 
      id: 3, 
 
      name: 'C', 
 
      x: Math.random() * 500, 
 
      y: Math.random() * 500 
 
     } 
 
     ]); 
 
    }, 3000); 
 
    
 
    function update(items) { 
 
     
 
     var node = nodeLayer.selectAll(".node") 
 
     .data(items, function(d) { 
 
      return d.id; 
 
     }); 
 
     
 
     node.exit().remove(); // exit, remove the g 
 

 
     nodeEnter = node.enter() // enter the g 
 
     .append("g") 
 
     .attr("class", "node"); 
 
     
 
     nodeEnter.append("circle") // enter the circle on the g 
 
     .attr("r", 2.5) 
 
     .attr('class', 'circle') 
 
     .attr('fill', 'red'); 
 

 
     nodeEnter.append("text") // enter the text on the g 
 
     .attr("dy", 3) 
 
     .attr('fill', 'green'); 
 
     
 
     node = nodeEnter.merge(node); // enter + update 
 
      
 
     node.attr('transform', function(d){ 
 
     return 'translate(' + d.x + ',' + d.y + ')'; 
 
     }); 
 
     
 
     node.select("text") 
 
     .text(function(d) { 
 
     return d.name; 
 
     }); 
 

 
    } 
 
    </script> 
 
</body> 
 

 
</html>

+0

Markありがとうございます。しかし、主な問題はまだ開いています。グループ内のサークル/テキストを更新するにはどうすればよいですか?その特定のケースの実例を提供したとしても、私は円/テキストを更新する必要があります。あなたの例に円/テキストの更新を追加できますか?私の例は誤解を招くかもしれません。実際に円/テキストをマージする必要はありません。 – Frame91

+0

@ Frame91、opps、そのユースケースを逃しました。上の更新されたコードスニペットを参照してください。 Enter + Updateの副選択としてテキストを選択するだけです。 – Mark

+0

鮮やかな答え - まさに私が探していたものです。 – Frame91

-1

私はこれを最近私のコードで行っています。私は要素を含む現在の選択に対してselect(subSelector)を使用します。次のようにあなたの例では、私はそれを変更します

function update(items) { 
var node = nodeLayer.selectAll(".node") 
    .data(items, function(d) { return d.id; }) 

var nodeEnter = node.enter() 
    .append("g") 
    .attr("class", "node"); 

nodeEnter.append("circle") 
    .attr("r", 2.5) 
    .attr('class', 'circle') 
    .merge(node.select('circle')) 
    .attr('fill', 'red'); 

nodeEnter.append("text") // insert 
    .attr("dy", 3) 
    .text(function(d) { return d.name; }) 
    .merge(node.select('text')) 
    .attr('fill', 'green'); 

// You only need to call remove on the group, all the other exit().remove() calls are superfluous 
node.exit().remove(); 

simulation 
    .nodes(items); 

}

-1

var svg = d3.select("svg"), 
 
    width = +svg.attr("width"), 
 
    height = +svg.attr("height"), 
 
    nodeLayer = svg.append('g'), 
 
    node; 
 

 
var list = []; 
 
var links = []; 
 

 
var simulation = d3.forceSimulation(list) 
 
    .force("charge", d3.forceManyBody().strength(-1000)) 
 
    .force("link", d3.forceLink(links).distance(200)) 
 
    .force("center", d3.forceCenter(width/2, height/2)) 
 
    .on("tick", ticked); 
 

 
function createNodes(index) { 
 
    links.push({ 
 
    'source': 0, 
 
    'target': index 
 
    }) 
 
    list.push({ 
 
    "id": index, 
 
    "name": "server " + index 
 
    }); 
 
    return list; 
 
} 
 

 
var iteration = 0; 
 
update(createNodes(iteration)); // just simulating updates 
 

 
d3.interval(function(timer) { 
 
    iteration++; 
 
    update(createNodes(iteration)); 
 
}, 1000); //<-- this was commented out incorrectly just now 
 

 
function update(items) { 
 
    var dataJoin = nodeLayer.selectAll(".node") 
 
    .data(items, function(d) { 
 
     return d.id; 
 
    }); 
 
    node = dataJoin.enter() // insert 
 
    .append("g") 
 
    .attr("class", "node"); 
 

 
    node.append("circle") // insert 
 
    .attr("r", 2.5) 
 
    .attr('class', 'circle') 
 
    .merge(dataJoin) // not the class, the actual selected group you called enter() on 
 
    .select('.circle') 
 
    .style('fill', 'red') // just for testing purposes 
 
    .exit().remove(); // exit 
 

 
    node.append("text") // insert 
 
    .attr("dy", 3) 
 
    .attr('class', 'text') 
 
    .text(function(d) { 
 
     return d.name; 
 
    }) 
 
    .merge(dataJoin) 
 
    .select('.text') 
 
    .style('fill', 'green') // fill is a style 
 

 
    dataJoin.exit().remove(); 
 
    simulation.nodes(list); 
 
    simulation.force("link").links(links); 
 
    simulation.alpha(1).restart(); 
 
} 
 

 
function ticked() { 
 
    node.attr("transform", function(d) { 
 
    var a = d.x || 0; 
 
    var b = d.y || 0; 
 
    return "translate(" + a + ", " + b + ")"; 
 
    }); 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.4.1/d3.min.js"></script> 
 
<svg height="300" width="300"></svg>

のバグの束があり、すべての '更新'(誤った名称)の

最初変更だけでなく、すべてのデータノードのリストで呼び出す必要があります。

https://bl.ocks.org/を探索し、人々が強制的なグラフをどのようにしているかをコピーすることができます。あなたは力を持っているリンクが必要です。

マージの背後にある考え方は、新しいリストと古いリストを比較することです。つまり、dataJoinまたはdata/idが関連付けられたグループを使用する必要があります。

私は専門家ではありません。力指向グラフのすべての例を見て、それらがどのように更新/マージするかを見てください。 (グラフを更新/再起動するには1つ以上の方法があります)

+0

は、マージの構文を示す固定および作業コードを提供していることを考慮して、否定的な投票に驚いた。あなたはこの質問をリメイクすることをお勧めします – softwarenewbie7331

+0

私も – Frame91

+0

あなたを投票していない、あなたの例は動作しません。 https://jsfiddle.net/cvvfsg97/7/を参照してください。ここで「テキスト」の例を使用しましたが、Johnsが「サークル」アプローチを採用しました。 – Frame91

関連する問題