2017-12-13 4 views
1

私はV4の一般的な更新パターンをうまく利用することに取り組んでいますが、私はmerge()を使って新しい動作を理解していると思います。私は奇妙な結果を経験しています。ここに私の更新機能があります:D3.enter()。merge()not working

function update(data) { 

    //I create and empty selection, and use the key function with an ID string 
    //in my dsv data. 
    var bubs = dataLr.selectAll(".data-bub") 
     .data(data, function(d) { 
      return d.id || (d.id = ++i); 
     }); 

    //remove any that dont need to be there. 
    //The first time around there wont be any nodes in the exit, but no matter. 
    bubs.exit() 
     .transition(tIntro) 
     .style("opacity", 0) 
     .each(function(d) { 
      //Log out the removed elements. 
      console.log(d.id); 
     }) 
     .remove(); 

    bubs.enter() //add any new ones - a group and a circle within it. 
     .append("g") 
     .classed("data-bub", true) 
     .on("click", function(d) { 
      console.log(d); 
     }) 
     .append("circle") 
     .attr("r", 20) 
     .classed("bub", true) 
     .merge(bubs);//here I merge the enter with the update. 


    //Now I should be able to run this transition that 
    //moves each group to a random location on my svg. 
    //But nothing happens. Why is the update selection empty after merge? 
    bubs.transition(tIntro) 
     .attr("transform", function(d, i) { 
      ///console.log(i); 
      var y = Math.random() * gHeight; 
      var x = Math.random() * gWidth; 
      return "translate(" + x + "," + y + ")"; 
     }); 

} 

さらに、別の奇妙なことが起こっています。現在、データを変更せずにこの機能を実行しています。したがって、exit()またはenter()で削除される要素はありません。しかし、2つのランダムなものが削除され、毎回再追加されますか?悪魔は何ですか?

答えて

1

.merge()選択を変更しません - d3v4での選択は不変です。一度宣言すると、選択範囲を再定義しない限り、選択範囲は常に同じになります。最初のselectAllメソッドが空の選択を返す場合、bubsは、bubsを再定義するまで、udpateの選択肢に何も含まれません。すべてのマージは:

その他の選択でこの選択をマージする新しい選択を返します。 (docs

あなたは、単に、あなたが使用することができ、g要素を追加した場合:

bubs.enter() 
    .append("g") 
    .merge(bubs) 
    // apply transition to enter and update selection 
    .transition()... 

または代わりに、マージによって返された選択でbubsを再定義:

bubs = bubs.enter() 
    .append("g") 
    .merge(bubs); 

// apply transition to enter and update selection 
bubs.transition().... 

しかし、あなたは2つの異なるタイプの要素の2つの選択肢があります:最初の選択がであるという点で、コードで問題が発生します10 - あなたのコードに基づいてg要素を選択し、入力された円の選択:あなたが適用された場合は、マージされた要素への移行は、あなたの移行が不均等に適用されます

bubs.enter()   
    .append("g")    // return entered g elements 
    .classed("data-bub", true) // return entered g elements with class data-bub 
    .append("circle")   // return entered circles 
    .merge(bubs);    // return entered circles with initially selected g elements 

- の場合は親g要素に更新の場合は子供にcircle要素が入る場合があります。これは望ましくない結果につながる可能性があります(たとえば、子のテキスト要素もある場合など)。この問題を解決する(とg要素に入力し、更新の両方への移行を適用)するには、の線に沿って何かを試みることができる:

var bubs = dataLr.selectAll(".data-bub") 
     .data(data, function(d) { return d.id || (d.id = ++i); }); 

    // remove as before 
    bubs.exit() 
     .remove(); 

    // enter new groups 
    var enter = bubs.enter() 
     .append("g") 
     .classed("data-bub", true); 

    // append circles to the new groups 
    enter.append("circle") 
     .attr("r", 20) 
     .classed("bub", true) 

    // merge enter and update, apply transition 
    enter.merge(bubs) 
     .transition().... 
+0

を私はあなたの最初の提案を試みたが、変換は、円と大きくないに適用されていますグループ、狂気の結果。試してみてくださいv2。ありがとうございました。 – dgfx

+0

はい、申し訳ありませんが、マージを使用していた選択が 'g'要素ではなく' circle'sの選択であることを忘れました。 v2は日付がついていて、ドキュメンテーションに欠けています。可能であれば、それを回避しようとします。 –

+0

これは動作しています。各選択を変数に追加すると、それぞれの選択が不変であることがわかります。しかし私の第二の問題はまだ残っています。入力データが変更されていないにもかかわらず、この更新機能が実行されるたびに、2つの要素が追加および削除されています。起こっているべきことは、既存の要素の新しい場所への移行です。 – dgfx