2012-09-18 14 views
11

d3を使用してフォースレイアウトを作成しました。これはうまくいきます。私の最初のデータがJSONファイルからロードされ、チャートはthis d3.js exampleに似ている技術を用いて描かれている:今のチャートは、私が上のノードを追加、更新、および削除する必要が画面上にあることをenter image description hered3フォースレイアウトの既存ノードを更新

私はウェブソケットを介して受け取るデータから飛ぶ。メソッドを追加したり削除したりしていますが、既存のノードのプロパティを更新する正しい方法を見つけることができません。

私はデータのソースを変更し、次にenter()メソッドを使用してグラフを更新するという正しい方法を取り入れたことを読んでいます。

function updateNode(id, word, size, trend, parent_id){  
    var updateNode = nodes.filter(function(d, i) { return d.id == id ? this : null; }); 
    if(updateNode[0]){ 
    updateNode.size = Number(size); 
    updateNode.trend = trend; 
    nodes[updateNode.index] = updateNode;  
    update(); 
    } 
} 

更新機能は、その後でノードを更新します:私はこれに適切なアプローチを取ってい

function update(){ 
    node = vis.selectAll('.node') 
    .data(nodes, function(d) { 
    return d.id; 
    }) 

    createNewNodes(node.enter()); 
    node.exit().remove(); 
    force.start(); 
} 

function createNewNodes(selection){  
    var slct = selection.append('g') 
    .attr('class', 'node') 
    .call(force.drag); 

    slct.append('circle') 
    .transition() 
    .duration(500) 
    .attr('r', function(d) { 
     if(d.size){ 
     return Math.sqrt(sizeScale(d.size)*40); 
     } 
    }) 
} 

私は次のことをやっているノードを更新するには

?このコードを試してみると、サークル上のradius属性を設定しようとするとノードとして取得するノードがノード配列の最後のノードになります。私。 1つのノードオブジェクトではなく、階層的なノードデータを含むノードです。

任意のポインタを大幅に私はこの上であまりにも多くの時間を費やしてきた、高く評価されるだろう:)

+0

はるかに単純な状況であるが、私は、同じ問題を抱えています。あなたは解決策を見つけましたか? –

+0

は、コードをオンラインエディタ(例:http://phrogz.net/JS/d3-playground/#BlankDefault)に入れることができます – ppoliani

答えて

7

あなたが必要とする複数のポイントがあります。私はあなたの質問から取得することです:

この質問に対する単純な答え「私は、再利用可能なパターンを使用しない方法」、マイク・ボストックからこの素晴らしいチュートリアル読むためにあなたを伝えるために、次のようになります。必要であればtowards reusable charts

をより多くの情報を持っているために、文書のこの選択は興味深いことができます:

、ここで私はあなたの特定の問題のために行うだろう実装のドラフトです:

function ForceGraph(selector,data) { 
    // This is the class that will create a graph 

    var _data = data 
    // Local variable representing the forceGraph data 

    svg = d3.select(selector) 
     .append('svg') 
    // Create the initial svg element and the utilities you will need. 
    // These are the actions that won't be necessary on update. 
    // For example creating the axis objects, your variables, or the svg container 

    this.data = function(value) { 
     if(!arguments.length) { 
     // accessor 
     return _data; 
     } 
     _data = value; 
     return this; 
     // setter, returns the forceGraph object 
    } 

    this.draw = function() { 
     // draw the force graph using data 

     // the method here is to use selections in order to do: 
     // selection.enter().attr(...) // insert new data 
     // selection.exit().attr(...) // remove data that is not used anymore 
     // selection.attr(...) // 

    } 
} 

var selector = "#graphId"; 
var data = {nodes: [...],links: [...]}; 
myGraph = new ForceGraph(selector,data); 
// Create the graph object 
// Having myGraph in the global scope makes it easier to call it from a json function or anywhere in the code (even other js files). 
myGraph.draw(); 
// Draw the graph for the first time 

// wait for something or for x seconds 

var newData = {nodes: [...],links: [...]}; 
// Get a new data object via json, user input or whatever 
myGraph.data(newData); 
// Set the graph data to be `newData` 
myGraph.draw(); 
// redraw the graph with `newData` 

あなたはおそらく見ることができるように、目標は、新しいノードを追加する機能を持つことではありません。目標は、既存のノードを更新または削除し、新しいノードを追加するだけで、強制的な有向グラフ全体を再描画することです。この方法では、描画コードは1回だけ書き込まれ、次にデータが変更されます。さらに読書のために

私が最初にこの問題に取り組んだ際に、この質問は私の宝の山だった:Updating links on a force directed graph from dynamic json data

関連する問題