2016-09-22 18 views
0

私はd3とsvgを初めて使用しました。私は様々な例の力強いグラフをまとめました。d3 force directed graph、javascript、svgのすべてのvarsをリセットする

初めてd3Graph()関数を呼び出すと、正しく描画されます(最初の画像)。私はそれをもう一度呼び出すと、それはしません(2番目の画像)。ページを更新してもう一度呼び出すと正しく動作します。私は明示的にすべての変数を無効にしていますので、なぜ再描画が正しく行われないのかわかりません。つまり、JSONを再読み込みして描画するように、ページの再読み込みと同じように動作させます。スクラッチから。

すべてのヘルプは素晴らしいことだ

第一呼び出しはありませんが、正しい引き分け:

d3 directed graph

さわやかページの問題もなく第二コール:

enter image description here

D3コード:「アクションに」あなたのコードへのリンクがあるかどう

function d3Graph() { 

var linkDistance = 100; 
var colors = d3.scale.category10(); 
var w = 1000; 
var h = 600; 

var links= null; 
var nodes= null; 
var force= null; 
var edges= null; 
var nodelabels= null; 
var edgepaths= null; 
var edgelabels= null; 
var svg= null; 

d3.select("svg").selectAll("*").remove(); 
$("#svg_container").empty(); 

svg = d3.select("#svg_container").append("svg").attr({ 
    "width" : w, 
    "height" : h 
}); 

d3.json("/workflows/graph.json?id=1", function(error, dataset) { 

    if (error) 
     throw error; 

    links = []; 
    dataset.edges.forEach(function(e) { 
     var sourceNode = dataset.nodes.filter(function(n) { 
     return n.id === e.source; 
     })[0], targetNode = dataset.nodes.filter(function(n) { 
     return n.id === e.target; 
     })[0]; 

     links.push({ 
      id : e.id, 
      edge_type : e.edge_type, 
      source : sourceNode, 
      target : targetNode 
     }); 
    }); 

    force = d3.layout.force().nodes(dataset.nodes).links(links).size([w, h]).linkDistance([linkDistance]).charge([-2000]).theta(0.1).gravity(0.05).start(); 

    edges = svg.selectAll("line").data(links).enter().append("line").attr("id", function(d, i) { 
     return 'edge' + i 
    }) 

    .attr('marker-end', function(d) { 
     if (d.edge_type == 'prerequisite') { 
      return 'url(#arrowhead)'; 
     } 
    }) 
    .attr('stroke', function(d) { 
     if (d.edge_type == 'prerequisite') { 
      return '#000'; 
     } else { 
      return '#F00'; 
     } 
    }) 

    nodes = svg.selectAll("circle").data(dataset.nodes).enter().append("circle").attr({ 
     "r" : 15 
    }).style("fill", function(d, i) { 
     return colors(i); 
    }).call(force.drag).on("click", function(d) { 
     $('#workflow_stage_id').val(d.id); 
     $('#workflow_stage_name').val(d.name); 
    }); 

    nodelabels = svg.selectAll(".nodelabel").data(dataset.nodes).enter().append("text").attr({ 
     "x" : function(d) { 
      return d.x; 
     }, 
     "y" : function(d) { 
      return d.y; 
     }, 
     "class" : "nodelabel", 
     "stroke" : "black" 
    }).text(function(d) { 
     return d.name + ' [ID:' + d.id + ']'; 
    }); 

    edgepaths = svg.selectAll(".edgepath").data(links).enter().append('path').attr({ 
     'd' : function(d) { 
      return 'M ' + d.source.x + ' ' + d.source.y + ' L ' + d.target.x + ' ' + d.target.y 
     }, 
     'class' : 'edgepath', 
     'fill-opacity' : 0, 
     'stroke-opacity' : 0, 
     'fill' : 'blue', 
     'stroke' : 'red', 
     'id' : function(d, i) { 
      return 'edgepath' + i 
     } 
    }) 

    edgelabels = svg.selectAll(".edgelabel").data(links).enter().append('text').on("click", function(d) { 
     $('#workflow_stage_edge_id').val(d.id); 
    }) 
    .attr({ 
     'class' : 'edgelabel', 
     'id' : function(d, i) { 
      return 'edgelabel' + i 
     }, 
     'dx' : 50, 
     'dy' : 0, 
     'font-size' : 14, 
     'fill' : '#000' 
    }); 

    edgelabels.append('textPath').attr('xlink:href', function(d, i) { 
     return '#edgepath' + i 
    }) 
    .text(function(d, i) { 
     return 'ID:' + d.id 
    }); 

    svg.append('defs').append('marker').attr({ 
     'id' : 'arrowhead', 
     'viewBox' : '-0 -5 10 10', 
     'refX' : 25, 
     'refY' : 0, 
     'orient' : 'auto', 
     'markerWidth' : 10, 
     'markerHeight' : 10, 
     'xoverflow' : 'visible' 
    }).append('svg:path').attr('d', 'M0 ,-5 L 10 ,0 L 0,5').attr('fill', '#000').attr('stroke', '#000'); 

    force.on("tick", function() { 

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

     nodes.attr({ 
      "cx" : function(d) { 
       return d.x; 
      }, 
      "cy" : function(d) { 
       return d.y; 
      } 
     }); 

     nodelabels.attr("x", function(d) { 
      return d.x; 
     }).attr("y", function(d) { 
      return d.y; 
     }); 

     edgepaths.attr('d', function(d) { 
      var path = 'M ' + d.source.x + ' ' + d.source.y + ' L ' + d.target.x + ' ' + d.target.y; 
      return path 
     }); 

     edgelabels.attr('transform', function(d, i) { 
      if (d.target.x < d.source.x) { 
       bbox = this.getBBox(); 
       rx = bbox.x + bbox.width/2; 
       ry = bbox.y + bbox.height/2; 
       return 'rotate(180 ' + rx + ' ' + ry + ')'; 
      } else { 
       return 'rotate(0)'; 
      } 
     }); 
    }); 
}); 
} 
+0

d3の入力、終了、更新のパターンを見てください。 – StackOverMySoul

+0

ありがとう@Davidlrntですが、私が理解しているように、データを動的に追加したり削除したりすることを理解していますか?私は、jsonのデータをバックエンドで変更する可能性があるため、グラフのjsonとリフレッシュ/再描画の完全な再読み取りを希望します。私はenter()呼び出しを見ることができますが、ノードオブジェクトを無効にすることは、例えばすべての参照を取り除くと思った – Simon

答えて

0

は、助けるために容易になるだろう。コンソールにエラーはありますか? とにかく、私はあなたが応答を得た後でもあなたの変数をきれいにしようとすることをお勧めします。以前のforce.tick()は強制的にnullに設定していてもバックグラウンドで実行されていたため、同様の問題が発生していました。したがって、次のようなものを試してみてください:

d3.json("/workflows/graph.json?id=1", function (error, dataset) { 

    if (error) 
      throw error; 

    if (force){ // check if force exists (should exist if you are calling it 2nd time) 
     force.stop(); 
     force = null; 

    // You can clean other variables here too, but with issue, which you show, looks more like force problem 

    } 

    //Here goes rest of your code 
} 

うまくいけば助かります。

関連する問題