2013-05-01 2 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)'이벤트가 (어떤 의미에서는) 글로벌 인 것처럼 보입니다. 즉, 'tick'이벤트에 대해 하나의 핸들러 만 가질 수 있으므로 마지막에 설치 한 핸들러가 호출됩니다. –

+0

D3 소스 코드를 잠깐 살펴 봤는데 그 일은 계속되고 있습니다. 파머. –

답변

2

당신은 jQuery 플러그인으로 generateMultiForce 기능을 쓸 수있는이 독립적 인 그래프를 유지하고 모두 힘 레이아웃을 적용 할 것 같다

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

다음 접근 방식은 힘, 노드 및 링크 데이터를 제한 그들의 힘을 지향하는 레이아웃으로 이렇게하면 노드 간 간섭을 일으키지 않고 동일한 SVG에 원하는만큼 레이아웃을 추가 할 수 있습니다. 각 레이아웃은 개별적으로 포맷 될 수 있습니다. 레이아웃이 서로 영향을 미치기를 바란다면 각각의 틱 기능을 편집 할 수 있습니다.

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(); 
} 

이제 제 2 힘 - 지향 배치는 동일한 구조를 가질 수 있으며,뿐만 아니라 동일한 변수 이름 :

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(); 
} 

마지막간에 데이터 인스턴스화 즉석에서 여러 레이아웃을 생성 할 수 있습니다. 희망은 당신이 찾고있는 것과 가깝습니다.

관련 문제