2017-02-23 19 views
0

d3.jsを使用してソートアルゴリズムのビジュアリゼーションを作成しようとしています。この目的のために、半径の異なるいくつかの円を作成し、ソートアルゴリズムの作業としてそれらを1つずつ交換したいと思います。これをやろうとすると、d3の選択に関連するデータを更新した後、.data()を使用してデータを取得しようとすると、変更されていないデータが取得されます(更新しなかったため)。この問題は、オブジェクトを追跡するのにkey関数を使用した場合にのみ発生します。キーを使用するとd3選択の更新データを取得できません

コードが続きます。 「チェック」をクリックすると、正しい初期状態であるコンソールに[1, 3, 2]が表示されます。 「do」をクリックすると、update関数が呼び出され、円は新しいデータに従って位置を変更します。ただし、再度「確認」をクリックすると、[1, 3, 2]が表示され、[3, 2, 1]は期待どおりに表示されません。

  1. なぜそれがこのように振る舞うん:

    ので、二つの質問がありますか?

  2. これを克服する、つまり選択から更新されたデータを取得する方法を教えてください。


 
    function key(d) { 
 
     return d 
 
     } 
 
    
 
    function update(data) { 
 
     return d3.select("#picture") 
 
     .selectAll("circle") 
 
     .data(data, key) 
 
     .transition() 
 
     .attr("cx", function(d, i) {return (i+1)*50;}); 
 
    } 
 
    
 
    $(function() { 
 
     d3.select("#picture") 
 
     .selectAll("circle") 
 
     .data([1, 3, 2], key) 
 
     .enter() 
 
     .append("circle") 
 
     .attr("cx", function(d, i) {return (i+1)*50;}) 
 
     .attr("cy", 100) 
 
     .attr("r", function(d) {return (d+1)*10;}) 
 
     .style("fill", "none") 
 
     .style("stroke", "steelblue"); 
 
     
 
     $("#do_it").click(function() { 
 
     update([3, 2, 1]); 
 
     }); 
 
     $("#check").click(function() { 
 
     console.log(d3.select("#picture") 
 
        .selectAll("circle").data()); 
 
     }); 
 
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
    <button id="check">check</button> 
 
    <button id="do_it">do</button><br/> 
 
    <svg id="picture" width=300 height=150></svg>

答えて

2

データの順序は正確には変更されませんキーを使用しているため。キーを使用していない場合、注文は変更されます。

円は、この関係を使用して作成された:

  • 0は基準データとして基準として
  • 1が有する3
  • 2を有する2として1を有しています。

各データムはキーとして使用され、円を識別します。データを更新すると、キーを設定しているため、この関係は変更されません。

console.logに更新後のデータ( "do it")を実行すると、新しいポジションのに関するデータは取得されません。あなたは、更新後のデータをCONSOLE.LOGすると、実際には、あなたが同じことを取得している:円22を持って

  • データとして円 13を持って
  • データとして

    • 01を持っていますデータムとして。

    これらは円のポジションではなく、作成された順序です。

    しかし、あなたはあなたのupdate関数内にconsole.logを置けば位置が変化していることがわかります。

    console.log("circle at position " + i + ", data: " + d) 
    

    は、デモをチェック「を行う」をクリックし、関連付けられたデータを参照してください

    function key(d) { 
     
         return d 
     
         } 
     
        
     
        function update(data) { 
     
         return d3.select("#picture") 
     
         .selectAll("circle") 
     
         .data(data, key) 
     
         .transition() 
     
         .attr("cx", function(d, i) { 
     
         console.log("circle at position " + i + ", data: " + d) 
     
         return (i+1)*50;}); 
     
        } 
     
        
     
        $(function() { 
     
         d3.select("#picture") 
     
         .selectAll("circle") 
     
         .data([1, 3, 2], key) 
     
         .enter() 
     
         .append("circle") 
     
         .attr("cx", function(d, i) {return (i+1)*50;}) 
     
         .attr("cy", 100) 
     
         .attr("r", function(d) {return (d+1)*10;}) 
     
         .style("fill", "none") 
     
         .style("stroke", "steelblue"); 
     
         
     
         $("#do_it").click(function() { 
     
         update([3, 2, 1]); 
     
         }); 
     
         $("#check").click(function() { 
     
         console.log(d3.select("#picture") 
     
            .selectAll("circle").data()); 
     
         }); 
     
        });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
     
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
     
        <button id="check">check</button> 
     
        <button id="do_it">do</button><br/> 
     
        <svg id="picture" width=300 height=150></svg>

    012:異なる 位置で円
    +0

    ありがとう!この場合、 '.data()'メソッドのようなものを使って要素の位置を取得する簡単な方法はないのは本当ですか? –

    +0

    はい、位置を取得できます。このフィドルをチェックすると、 'console'に大きな円のx位置が表示されます:https://jsfiddle.net/gerardofurtado/fget7ouu/ –

    +0

    良い!私は実際に 'do'と 'check'を押した後に '[3、2、1]'のような配列を取得したいと思っています。私は 'cx'やタグの中の' cx'と一緒に再構築しようとしますが、値の配列を取得する方法はまだ分かりません。 –

    1

    Gerardo Furtadoの答えは、このような動作の理由を説明しています。ここでは、私の質問の2番目の部分に答えています:これを克服する方法。

    私は要素の実際の位置をそのdata-position属性に格納しておき、その位置情報から元のデータを復元します。

    私はこれが最も洗練された解決策であるとは確信していません。そのため、コメントや代替案が高く評価されています。詳細な説明のための

    function key(d) { 
     
        return d 
     
    } 
     
    
     
    function update(data) { 
     
        return d3.select("#picture") 
     
        .selectAll("circle") 
     
        .data(data, key) 
     
        .transition() 
     
        .attr("cx", function(d, i) { 
     
         return (i + 1) * 50; 
     
        }) 
     
        .attr("data-position", function(d, i) { 
     
         return i; 
     
        }); 
     
    } 
     
    
     
    function get_data(initial_array) { 
     
        // BASED ON: http://stackoverflow.com/a/22118052/3025981 
     
        var indexes = [] 
     
        d3.select("#picture") 
     
        .selectAll("circle").each(function(d, i) { 
     
         indexes.push(+d3.select(this).attr('data-position')) 
     
        }); 
     
        // END BASED 
     
        var data = [] 
     
        for (i = 0; i < initial_array.length; i++) { 
     
        data[indexes[i]] = initial_array[i]; 
     
        } 
     
        return data; 
     
    } 
     
    
     
    $(function() { 
     
        initial_array = [1, 3, 2] 
     
        d3.select("#picture") 
     
        .selectAll("circle") 
     
        .data(initial_array, key) 
     
        .enter() 
     
        .append("circle") 
     
        .attr("cx", function(d, i) { 
     
         return (i + 1) * 50; 
     
        }) 
     
        .attr("cy", 100) 
     
        .attr("r", function(d) { 
     
         return (d + 1) * 10; 
     
        }) 
     
        .attr("data-position", function(d, i) { 
     
         return i; 
     
        }) 
     
        .style("fill", "none") 
     
        .style("stroke", "steelblue"); 
     
    
     
        $("#do_it").click(function() { 
     
        update([3, 2, 1]); 
     
        }); 
     
        $("#check").click(function() { 
     
        console.log(get_data(initial_array)); 
     
        }); 
     
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
     
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
     
    <button id="check">check</button> 
     
    <button id="do_it">do</button> 
     
    <br/> 
     
    <svg id="picture" widht=300 height=300></svg>

    関連する問題