2012-07-09 4 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コードのように行く:レディ機能でdrawGraph()を呼び出すことに加えて

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

+2

私はこの答えを理解できません。それを理解できるように助けてくれる人が誰でも、私はそれを使うことができます。 –

+0

ちょうどいくつかの観測では、svgを含むはずの要素はGraphコンストラクタのパラメータですが、ハードコードされた値が代わりに使用されます。また、removeallLinksのように、関数の命名が一貫してcamelCasedではありません。 – glasspill

0

、あなたはまた、インライン<script></script>ブロック内の掲載コードを埋め込むことができます。

これは、d3サイトのチュートリアルのほとんどがそれを処理する方法です。

12

私はRahulsの偉大な例をとり、いくつかの変更を行い、誰かが完全に機能する例に興味を持っていれば、時間の経過とともにアニメーションを含むblockを投稿しました。リンク/ノードの追加/削除はこれよりも簡単ですが、まだかなりクールです。

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

enter image description here

+3

あなたのブロックのコードについて。 ** link.enter()。append( "line")**を** link.enter()。insert( "line"、 "g")に変更することで、Jqueryを使用してDOMを並べ替えることを避けることができます。 – timebandit

関連する問題