2012-09-18 42 views
11

我已經使用d3創建了一個強制佈局,並且效果很好。我最初的數據是從JSON文件加載和圖表繪製類似於this d3.js example技術:在d3 Force Layout中更新現有節點

enter image description here

現在,該圖是我需要補充,更新和刪除節點上的屏幕上從我通過網絡套接字接收的數據飛行。我有添加和刪除方法的工作,但我找不到更新現有節點的屬性的正確方法。

從我所進行的閱讀中我收集了正確的技術是更改數據源,然後使用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屬性時獲得的節點是節點數組中的最後一個節點。即包含分層節點數據而不是單個節點對象的數據庫。

任何指針將不勝感激,我已經花了太多時間在這:)

+0

我有同樣的問題,雖然在一個更簡單的環境。你找到解決方案嗎? – 2013-03-01 14:27:53

+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` 

正如你可能會看到,我們的目標是不是有一個函數來添加一個新的節點。目標是通過更新或刪除現有節點並添加新節點來重新繪製整個強制指令圖。通過這種方式,繪圖代碼只寫入一次,然後只有數據發生變化。

對於進一步的閱讀,這個問題是我的金礦當我第一次解決了這個問題:Updating links on a force directed graph from dynamic json data