2012-07-09 34 views
34

我是D3新手,正在研究json數據是動態的強制有向圖。我能夠在接收到新數據後更改力圖,但這種情況會隨着彈性效應而發生。創建我的力量圖形的代碼是:從動態json數據更新鏈接在力向圖上

<div class="graph"></div> 
<script> 
var w = 660, 
    h = 700, 
    r = 10; 
var vis = d3.select(".graph") 
    .append("svg:svg") 
    .attr("width", w) 
    .attr("height", h) 
    .attr("pointer-events", "all") 
    .append('svg:g') 
    .call(d3.behavior.zoom().on("zoom", redraw)) 
    .append('svg:g'); 
vis.append('svg:rect') 
    .attr('width', w) 
    .attr('height', h) 
    .attr('fill', 'rgba(1,1,1,0)'); 
function redraw() { 
    console.log("here", d3.event.translate, d3.event.scale); 
    vis.attr("transform", "translate(" + d3.event.translate + ")" + 
          " scale(" + d3.event.scale + ")"); 
}; 

var force = d3.layout.force() 
    .gravity(.05) 
    .charge(-200) 
    .linkDistance(260) 
    .size([w, h]); 

var svg = d3.select(".text") 
    .append("svg") 
    .attr("width", w) 
    .attr("height", h); 

d3.json(graph, function(json) { 

    var nodeList = json.nodes; 
    var link = vis.selectAll("line") 
     .data(json.links) 
     .enter() 
     .append("line") 
     .attr("stroke-opacity", function(d) { 
      if(d.label == 'is a') { 
       return '0.8'; 
      } else { 
       return '0.2'; 
      }; 
     }) 
     .attr("stroke-width", function(d) { 
      if(d.value !== null) { 
       return d.value; 
      } else { 
       return 2; 
      }; 
     }) 
     .style("stroke", function(d) { 
      if(d.color !== null) { 
       return d.color; 
      }; 
     }) 
     .on("mouseover", function() { 
      d3.select(this) 
       .style("stroke", "#999999") 
       .attr("stroke-opacity", "1.0"); 
     }) 
     .on("mouseout", function() { 
      d3.select(this) 
       .style("stroke", function(d) { 
        if(d.color !== null) { 
         return d.color; 
        }; 
       }) 
       .attr("stroke-opacity", function(d) { 
        if(d.label == 'is a') { 
         return '0.8'; 
        } else { 
         return '0.2'; 
        }; 
       }) 
      }); 

    link.append("title") 
     .text(function(d) { return d.label });   

    var node = vis.selectAll("g.node") 
     .data(json.nodes) 
     .enter() 
     .append("svg:g") 
     .attr("class","node") 
     .call(force.drag); 

    node.append("svg:circle") 
     .attr("r", function(d) { 
      if (d.size > 0) { 
       return 10+(d.size*2); 
      } else { 
       return 10; 
      } 
     }) 
     .attr("id", function(d) { return "Node;"+d.id; }) 
     .style("fill", function(d) { 
      if(d.style == 'filled') { 
       return d.color; 
      }; 
     }) 
     .style("stroke", function(d) { 
      if(d.style !== 'filled') { 
       return d.color; 
      }; 
     }) 
     .style("stroke-width", "2") 
     .on("mouseover", function() { 
      d3.select(this).style("fill", "#999"); 
      fade(.1); 
     }) 
     .on("mouseout", function(d) { 
      if (d.style == 'filled') { 
       d3.select(this).style("fill",d.color);fade(1); 
      } else { 
       d3.select(this).style("stroke",d.color); 
       d3.select(this).style("fill","black"); 
      } 
      fade(1); 
     }); 

    node.append("title") 
     .text(function(d) { return d.Location; });   

    force.nodes(json.nodes) 
     .links(json.links) 
     .on("tick", tick) 
     .alpha(1) 
     .start(); 

    function tick() { 
    node.attr("cx", function(d) { return d.x; }) 
     .attr("cy", function(d) { return d.y; }) 
     .attr("transform", function(d) { 
      return "translate(" + d.x + "," + d.y + ")"; 
    }); 

    link.attr("x1", function(d) { return d.source.x; }) 
     .attr("y1", function(d) { return d.source.y; }) 
     .attr("x2", function(d) { return d.target.x; }) 
     .attr("y2", function(d) { return d.target.y; }); 
    } 

}); 
</script> 

我能夠創造當一個新的JSON字符串被再次召回整體功能獲得了新的圖形。這將創建一個新的圖來代替舊的圖。在收到值時,我無法使用新的一組值更新舊圖;我的圖中的節點不會改變,只是它們之間的關係發生改變。

我確實發現了一個例子(http://bl.ocks.org/1095795),其中一個新節點被刪除並重新創建,但實現有點不同。

任何指針或幫助將非常感激。

回答

55

那麼我可以找到解決方案瀏覽,在這裏發佈給需要幫助的人在這個主題。這個想法是創建一個圖的對象,並與節點和鏈接數組一起玩耍。 的JS代碼都爲:

var graph; 
function myGraph(el) { 

// Add and remove elements on the graph object 
this.addNode = function (id) { 
    nodes.push({"id":id}); 
    update(); 
}; 

this.removeNode = function (id) { 
    var i = 0; 
    var n = findNode(id); 
    while (i < links.length) { 
     if ((links[i]['source'] == n)||(links[i]['target'] == n)) 
     { 
      links.splice(i,1); 
     } 
     else i++; 
    } 
    nodes.splice(findNodeIndex(id),1); 
    update(); 
}; 

this.removeLink = function (source,target){ 
    for(var i=0;i<links.length;i++) 
    { 
     if(links[i].source.id == source && links[i].target.id == target) 
     { 
      links.splice(i,1); 
      break; 
     } 
    } 
    update(); 
}; 

this.removeallLinks = function(){ 
    links.splice(0,links.length); 
    update(); 
}; 

this.removeAllNodes = function(){ 
    nodes.splice(0,links.length); 
    update(); 
}; 

this.addLink = function (source, target, value) { 
    links.push({"source":findNode(source),"target":findNode(target),"value":value}); 
    update(); 
}; 

var findNode = function(id) { 
    for (var i in nodes) { 
     if (nodes[i]["id"] === id) return nodes[i];}; 
}; 

var findNodeIndex = function(id) { 
    for (var i=0;i<nodes.length;i++) { 
     if (nodes[i].id==id){ 
      return i; 
     } 
     }; 
}; 

// set up the D3 visualisation in the specified element 
var w = 500, 
    h = 500; 
var vis = d3.select("#svgdiv") 
    .append("svg:svg") 
    .attr("width", w) 
    .attr("height", h) 
    .attr("id","svg") 
    .attr("pointer-events", "all") 
    .attr("viewBox","0 0 "+w+" "+h) 
    .attr("perserveAspectRatio","xMinYMid") 
    .append('svg:g'); 

var force = d3.layout.force(); 

var nodes = force.nodes(), 
    links = force.links(); 

var update = function() { 
     var link = vis.selectAll("line") 
     .data(links, function(d) { 
      return d.source.id + "-" + d.target.id; 
      }); 

    link.enter().append("line") 
     .attr("id",function(d){return d.source.id + "-" + d.target.id;}) 
     .attr("class","link"); 
    link.append("title") 
    .text(function(d){ 
     return d.value; 
    }); 
    link.exit().remove(); 

    var node = vis.selectAll("g.node") 
     .data(nodes, function(d) { 
      return d.id;}); 

    var nodeEnter = node.enter().append("g") 
     .attr("class", "node") 
     .call(force.drag); 

    nodeEnter.append("svg:circle") 
    .attr("r", 16) 
    .attr("id",function(d) { return "Node;"+d.id;}) 
    .attr("class","nodeStrokeClass"); 

    nodeEnter.append("svg:text") 
    .attr("class","textClass") 
    .text(function(d){return d.id;}) ; 

    node.exit().remove(); 
    force.on("tick", function() { 

     node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y   + ")"; }); 

     link.attr("x1", function(d) { return d.source.x; }) 
      .attr("y1", function(d) { return d.source.y; }) 
      .attr("x2", function(d) { return d.target.x; }) 
      .attr("y2", function(d) { return d.target.y; }); 
    }); 

    // Restart the force layout. 
    force 
    .gravity(.05) 
    .distance(50) 
    .linkDistance(50) 
    .size([w, h]) 
    .start(); 
}; 


// Make it all go 
update(); 
} 

function drawGraph() 
{ 
graph = new myGraph("#svgdiv"); 
graph.addNode('A'); 
graph.addNode('B'); 
graph.addNode('C'); 
graph.addLink('A','B','10'); 
graph.addLink('A','C','8'); 
graph.addLink('B','C','15'); 
} 
+1

@Rahul基本上你重繪整個圖形? – Pramod 2013-05-21 10:10:22

+2

我無法理解這個答案。任何人都可以幫助我理解它,以便我可以使用它。 – 2013-06-08 06:44:14

+0

只是一對觀察值,應該包含svg的元素是Graph構造函數的參數,但是會使用硬編碼的值代替。此外,功能命名不一致camelCased,如removeallLinks。 – glasspill 2016-08-22 12:34:39

0

除了準備函數調用drawGraph(),您還可以嵌入一個內嵌<script></script>塊內張貼的代碼。

這是d3網站上的大多數教程如何處理它的方式。

12

我拿Rahuls的一個很好的例子做了一些改變,並且隨着時間的推移發佈了一個帶動畫的bl.ock,如果有人對一個功能完整的例子感興趣的話。添加/刪除鏈接/節點應該比這更容易,但仍然非常酷。

http://bl.ocks.org/ericcoopey/6c602d7cb14b25c179a4

enter image description here

+3

關於你的塊的代碼。你可以通過改變** link.enter()。append(「line」)**到** link.enter()。insert(「line」,「g」)**來避免使用Jquery重新排序DOM。 – timebandit 2015-06-24 22:18:45