10

私はd3のパックレイアウト(http://bl.ocks.org/4063530)に頭を悩ませようとしています。

基本的なレイアウトは機能していますが、新しいデータで更新したいと思います。つまり、新しいデータを収集し、それを現在のlayout.packにバインドし、それに応じて更新します(update / exit / enter)。

私の試みはここにあります(http://jsfiddle.net/emepyc/n4xk8/14/):

var bPack = function(vis) {
    var pack = d3.layout.pack()
    .size([400,400])
    .value(function(d) {return d.time});

    var node = vis.data([data])
    .selectAll("g.node")
    .data(pack.nodes)
    .enter()
    .append("g")
    .attr("class", function(d) { return d.children ? "node" : "leaf node"; })
    .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

node.append("circle")
    .attr("r", function(d) { return d.r });

    node.filter(function(d) { return !d.children; }).append("text")
    .attr("text-anchor", "middle")
    .attr("dy", ".3em")
    .text(function(d) { return d.analysis_id });

    bPack.update = function(new_data) {
        console.log("UPDATE");

        node
        .data([new_data])
        .selectAll("g.node")
        .data(pack.nodes);

        node
        .transition()
        .duration(1000)
        .attr("class", function(d) { return d.children ? "node" : "leaf node" })
    .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")" });

        node.selectAll("circle")
        .data(new_data)
        .transition()
    .duration(1000)
    .attr("r", function(d) { return d.r; });

    };

特定の質問...

データをバインドするにはどうすればよいですか?(データは複雑な構造ではなく、データの配列でもないため)

新しいノード/リーフをレイアウトに追加するにはどうすればよいですか?そして古いものは削除されましたか?

実例へのポインタをいただければ幸いです。

4

3 に答える 3

10

実例はこちらです。

基本的に、初期ロードのコードがあり、すべての円、ツールチップなどが作成され、初期の場所に配置されます。また、レイアウト(パック)も作成されます。

それよりも、ボタンを押すたびに、新しいデータがパックにロードされ、パックが再計算されます。その重要なコードはここにあります:

ここで、データをパックレイアウトにバインド(ロード)します:(私の例では、そのランダムデータ、もちろん、jsonまたはコードなどからのデータがあります):

pack.value(function(d) { return 1 +
             Math.floor(Math.random()*501); });

ここで、新しいレイアウトが計算されます。

pack.nodes(data);

その後、要素は新しい位置に移行され、その属性は必要に応じて変更されます。

このような例では不必要な複雑さが生じると思うので、入力/更新/終了のパターンや変換(他のソリューションで見られる可能性があります)を使用しないことを強調したいと思います。

トランジションが動作している写真を次に示します。

始める:

始める

遷移:

遷移

終わり:

終わり

于 2013-12-29T12:21:08.023 に答える
4

最近同じ問題が発生し、一般的な更新パターンのチュートリアルにも出くわしました。これらは私の目的を果たしませんでした。グラフ(ForceLayout)に数百のDOM要素があり、個々のノードごとのプロパティを含むRESTデータを受信して​​いました。mg1075の提案に応えて言ったように、データを再バインドして更新すると、グラフ全体が再構築されました。私の場合、DOMの更新が完了するまでに数分かかりました。

後で更新する必要のある要素に一意のIDを割り当てることになり、JQueryでそれらを選択しました。グラフのセットアップ全体でD3を使用していますが、更新では使用していません。これは気分が悪いですが、問題なく動作します。ほとんどのDOMを破棄して再作成するのに数分かかる代わりに、3秒ほどかかります(REST呼び出しのタイミングを省略します)。D3でプロパティの更新などができなかった理由はわかりません。

おそらく、Mike Bostockがremove()または適切なサブ選択関数をenter()選択に追加した場合、純粋なD3パターンに従って更新を行うことができます。これを理解している間、私はデータのサブセットをバインドしようとして、新しいプロパティが追加されたデータをバインドし、更新が必要な要素を取得するためにサブ選択しましたが、入力の制限された特定の性質のために機能しませんでした()選択。

于 2013-09-05T17:07:45.660 に答える
3

関連性がありますが、まだ確認していない場合:http:
//bl.ocks.org/3808218-一般的な更新パターン、I
http://bl.ocks.org/3808221-一般的な更新パターン、II
http://bl。 ocks.org/3808234-一般的な更新パターン、III

このサンプルフィドルにはトランジションはありませんが、データを更新するための少なくとも1つのアプローチがあります。

http://jsfiddle.net/jmKH6/

//  VISUALIZATION
var svg = d3.select("#kk")
    .append("svg")
    .attr("width", 500)
    .attr("height", 600)
    .attr("class", "pack"); 

var g = svg.append("g")
    .attr("transform", "translate(2,2)");

var pack = d3.layout.pack()
        .size([400,400])
        .value(function(d) {return d.time});

function update(data) {

    var nodeStringLenth = d3.selectAll("g.node").toString().length; 
    if ( nodeStringLenth > 0) {
        d3.selectAll("g.node")
            .remove();
    }

    var node = g.data([data]).selectAll("g.node")
            .data(pack.nodes);

        node.enter()
          .append("g")
            .attr("class", function(d) { return d.children ? "node" : "leaf node"; })
            .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

        node.append("circle")
            .attr("r", function(d) { return d.r });

        node.filter(function(d) { return !d.children; }).append("text")
            .attr("text-anchor", "middle")
            .attr("dy", ".3em")
            .text(function(d) { return d.analysis_id });

       node
            .exit()
            .remove();
}


var myData = [data1, data2, data3];
update(data1); 
setInterval(function() {
    update( myData[Math.floor(Math.random() * myData.length)] );  // http://stackoverflow.com/questions/4550505/getting-random-value-from-an-array?lq=1
}, 1500);
于 2013-02-10T08:34:18.733 に答える