2017-07-13 12 views
1

私は動的にフォームのJSONファイルからグラフを作成しようとしています:ダイナミックD3力グラフ

{"nodes": [{"category": "...", "group": 1, "uid": 0, "number": 1, "complaints": [" ...,..."], "name": "..."}], "links": ['source':"",'target':"",'value':""]} 

私は新しいノードを追加するときが表示されることを望むように私は正しくグラフを描くことができ、エッジが正しく形成されておらず、どちらもノードの半径ではありません(JSONのnumber要素に従って変更されています)。d3でこれを行う方法を文書化したチュートリアルやコードを見つけることができませんでした。しかし、ページをリフレッシュすると、グラフが表示されます。

これはこれまで試みてきたコードです。私はそれが働くために作られる必要があるわずかな変更があるように感じるが、私はそれが何であるか把握できない。私がページをリフレッシュするときにそれが欲しいと表示するという事実は、リスタート機能に何か問題があることを私に伝えます。

<html> 
    <head> 
     <style> 
      .node { 
       stroke: #fff; 
       stroke-width: 1.5px; 
      } 
      .link { 
       stroke: #999; 
       stroke-opacity: .6; 
      } 
      d3-tip { 
       line-height: 1; 
       color: black; 
      } 
     </style> 
     <script src="https://d3js.org/d3.v3.min.js"></script> 
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> 
     <script type='text/javascript' src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"> </script> 
    </head> 

    <b> 
    </b> 



    <script> 

     $.ajaxSetup({cache: false}); 
     var json; 
     getJSON(); 
     function getJSON(){ 
       $.ajax({ 
        'async': false, 
        'global': false, 
        'url': "/categories.json", 
        'dataType': "json", 
        'success': function (data) { 
         json = data; 
         console.log("Updating JSON") 
        } 
       }); 
       return json; 
     } 

     window.setInterval(function(){ 
      getJSON(); 
      restart(); 
     }, 5000); 


     var width = 500, 
      height = 500; 

     var color = d3.scale.category20(); 

     var force = d3.layout.force() 
      .charge(-120) 
      .linkDistance(30) 
      .size([width, height]); 

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

     var tip = d3.tip() 
      .attr('class', 'd3-tip') 
      .offset([-10, 0]) 
      .html(function (d) { 
      return d.name + "</span>"; 
     }) 
     svg.call(tip); 

     force.nodes(json.nodes) 
      .links(json.links) 
      .start(); 

     var link = svg.selectAll(".link") 
      .data(json.links) 
      .enter().append("line") 
      .attr("class", "link") 
      .style("stroke-width", function (d) { 
      return Math.sqrt(d.value); 
     }); 

     var node = svg.selectAll(".node") 
      .data(json.nodes) 
      .enter().append("circle") 
      .attr("class", "node") 
      .attr("r", function(d) { 
       if(d.number >= 20){ 
        return 50; 
       } 
       if(d.number > 1){ 
        return ((d.number*1.3)+10); 
       }else{ 
        return d.number+4 
       } 

      }) 
      .style("fill", function (d) { 
      return color(d.group); 
     }) 
     .call(force.drag) 
     .on('mouseover', tip.show) 
     .on('mouseout', tip.hide); 

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

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

     function restart() { 

      force = d3.layout.force() 
      .charge(-120) 
      .linkDistance(30) 
      .size([width, height]); 

      tip = d3.tip() 
      .attr('class', 'd3-tip') 
      .offset([-10, 0]) 
      .html(function (d) { 
      return d.name + "</span>"; 
      }) 
      svg.call(tip); 

      link = svg.selectAll(".link") 
      .data(json.links) 
      .enter().append("line") 
      .attr("class", "link") 
      .style("stroke-width", function (d) { 
      return Math.sqrt(d.value); 
      });; 

      // Apply the general update pattern to the nodes. 
      node = svg.selectAll(".node") 
      .data(json.nodes) 
      .enter().append("circle") 
      .attr("class", "node") 
      .attr("r", function(d) { 
       if(d.number >= 20){ 
        return 50; 
       } 
       if(d.number > 1){ 
        return ((d.number*1.3)+10); 
       }else{ 
        return d.number+4 
       } 

      }) 
      .style("fill", function (d) { 
      return color(d.group); 
      }) 
      .call(force.drag) 
      .on('mouseover', tip.show) 
      .on('mouseout', tip.hide); 

      force.nodes(json.nodes) 
      .links(json.links) 
      .start(); 

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

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


     } 
    </script> 

</html> 

答えて

1

ここにあなたのJSON形式を使用して2つのノードと1つのリンクとminimal working example on plunkerです。

あなたの目的がrestart()で何であるかは完全にはわかりませんが、ファイルからデータを一度ロードしていると思いますか?いずれにしても、フォースレイアウト上で全く同じロジックを2回使用する必要はありません。関数内でd3の追加/更新/削除ロジックを持つことができ、データが変更されたときにその関数を呼び出します。ティック機能は、一度だけ指定する必要があります。

デバッグしたくないツールチップコードをコメントアウトしましたが、リンクされたリソースはhttpsではないと思います! http://blockbuilder.org/searchは、良い例を見つけるのに役立つかもしれないd3の例を検索するための優れたリソースです。

回答に満足している場合は、受け入れられた回答とupvoteとしてマークしてください。

+0

私は動的に新しいノードをグラフに追加しようとしていますが、JSONファイルを再ロードする理由は、新しい要素が追加されるとそれが絶えず変化するためです。私はグラフを描くことができますが、新しいノードを適切に追加することはできません。 –

+0

あなたのコードでは、新しいデータを扱うのはenter()です。リフレッシュされたデータセットを適切に処理するには、更新と削除を処理する必要があります。 d3は、追加/更新/削除であるかどうかを判断するためにdom要素をデータセットと比較します。あなたはこれをやっていません。良い解説については、この記事を参照してください。https://medium.com/@c_behrens/enter-update-exit-6cafc6014c36 – Robatron