2013-05-01 58 views
6

我已經看到了在單個頁面上創建多個強制佈局的解決方案,其中每個佈局都包含在它自己的SVG中;但是,我一直無法找到如何在單個SVG中包含多個強制佈局的幫助。每個佈局都有自己的數據與之相關聯。D3:一個SVG中的多個力佈局?

我現在在做的一個例子可以在http://jsfiddle.net/connorgr/SRAJa/找到。我已經包含了下面代碼的關鍵部分。最終的結果看起來非常像,除了最後一個節點/鏈接數據外,所有的佈局從未被激活(或刪除)。有什麼辦法來防止這種情況的發生?

由於我正在構建可視化的用例,我無法將數據合併在一起並僅使用一種佈局。

/** 
    * Creates a force layout in svgObj for each element in graphs 
    * (svg) svgObj - The SVG to include the force layouts in 
    * (json) graphs - An array of {"nodes":[...],"links":[...]} objects 
    */ 
function generateMultiForce(svgObj, graphs) { 
    for(var i=0; i < graphs.length; i++) { 
    var graph = graphs[i]; 

    var graphArea = svgObj.append("g"); 

    var force = d3.layout.force() 
     .charge(-200) 
     .linkDistance(45) 
     .size([width, height]) 
     .nodes(graph.nodes) 
     .links(graph.links) 
     .start(); 

    var link = graphArea.selectAll(".link") 
     .data(graph.links) 
     .enter().append("line") 
      .attr("class", "link"); 

    var nodeGroup = graphArea.selectAll("g") 
     .data(graph.nodes) 
     .enter().append("g") 
     .call(force.drag); 

    var node = nodeGroup.append("circle") 
     .attr("class", "node") 
     .attr("r", 5) 
     .style("fill", function(d) { 
      return color(d.group); }); 

    var text = nodeGroup.append("text") 
     .attr("x", 8) 
     .attr("y", ".31em") 
     .text(function(d) { return d.name; }); 

    force.on("tick", function() { 
     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; }); 

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

它看起來像'滴答'事件是(在某種意義上)全球。也就是說,你可以只有一個'tick'事件的處理程序,所以你安裝的最後一個被調用。 – 2013-05-01 19:00:39

+0

簡單介紹了D3源代碼,看起來確實如此。遊民。 – 2013-05-05 12:44:38

回答

2

你可以寫generateMultiForce功能的jQuery插件 - 這似乎保持圖表獨立和應用力佈局都:

var width = 600, 
    height = 600; 

var color = d3.scale.category20(); 

var data = [ 
    { 
    "nodes": [ 
     {"name": "Hello"}, 
     {"name": "World"} 
    ], 
    "links": [ 
     {"source": 0, "target": 1, "value": 0.5} 
    ] 
    }, 
    { 
    "nodes": [ 
     {"name": "Zero"}, 
     {"name": "One"}, 
     {"name": "Two"} 
    ], 
    "links": [ 
     {"source": 0, "target": 1, "value": 0.25}, 
     {"source": 1, "target": 2, "value": 0.5}, 
     {"source": 2, "target": 0, "value": 0.25} 
    ] 
    } 
]; 

(function($) { 
    $.fn.generateMultiForce = function(svgObj) { 

     return this.each(function() { 
      var graph = this; 
      var graphArea = svgObj.append("g"); 

      var force = d3.layout.force() 
       .charge(-200) 
       .linkDistance(45) 
       .size([width, height]) 
       .nodes(graph.nodes) 
       .links(graph.links) 
       .start(); 

      var link = graphArea.selectAll(".link") 
       .data(graph.links) 
       .enter().append("line") 
       .attr("class", "link"); 

      var nodeGroup = graphArea.selectAll("g") 
       .data(graph.nodes) 
       .enter().append("g") 
       .call(force.drag); 

      var node = nodeGroup.append("circle") 
       .attr("class", "node") 
       .attr("r", 5) 
       .style("fill", function(d) { 
        return color(d.group); }); 

      var text = nodeGroup.append("text") 
       .attr("x", 8) 
       .attr("y", ".31em") 
       .text(function(d) { return d.name; }); 

      force.on("tick", function() { 
       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; }); 

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

var svgTest = d3.select("body").append("svg") 
    .attr("width", width) 
    .attr("height", height); 

$(data).generateMultiForce(svgTest); 
6

以下辦法限制力,節點和鏈路數據到他們相應的力量指導佈局。通過這種方式,您可以根據需要添加儘可能多的佈局,而不會造成節點間干擾。每個佈局可以單獨格式化。如果你最終希望佈局互相影響,你可以編輯它們各自的tick函數。

function layout1(inputNodes, inputLinks) { 
    var force = d3.layout.force(); 
    var nodes = force.nodes(); 
    var links = force.links(); 

    var update = function() { 
     //append nodes and links from data 

     force.on("tick",function(e){ 
     //tick movement 

     } 
    } 
    for(var i=0; i<inputNodes.length; i++){ 
     nodes.push(inputNodes[i]); 
    } 
    for(var i=0; i<inputLinks.length; i++){ 
     links.push(inputLinks[i]); 
    } 
    update(); 
} 

現在第二力指向佈局可以具有相同的結構,並且相同的變量名,以及:

var layout1 = new layout1(inputNodes, inputLinks); 
var layout2 = new layout2(inputNodes, inputLinks); 

此方法:

function layout2(inputNodes, inputLinks) { 
    var force = d3.layout.force(); 
    var nodes = force.nodes(); 
    var links = force.links(); 

    var update = function() { 
     //append nodes and links from data 

     force.on("tick",function(e){ 
     //tick movement 

     } 
    } 
    for(var i=0; i<inputNodes.length; i++){ 
     nodes.push(inputNodes[i]); 
    } 
    for(var i=0; i<inputLinks.length; i++){ 
     links.push(inputLinks[i]); 
    } 
    update(); 
} 

與任何數據最後實例化可以通過動態創建多個佈局。希望接近你正在尋找的東西。