arianit
arianit

Reputation: 107

D3.js multiple force layout graphs from json file

I have defined the following function which reads data from a JSON file "on button click" and it should generate multiple d3 graphs, each in its own svg container:

    //button click 
function updateData() {
    var c = $("#select-list option:selected").text();

    d3.json("out_graph.json", function(subgraphs, ind) {
   for (k in ind) {
        var k_data = ind[k].graphs;
        if (k_data.values = c)
            {
            console.log(k_data.values ); //works
            var svgSUBS = d3.select("#subgraphs").append("svg")
                            .attr("id","subsID")
                            .attr("width", 300)
                            .attr("height", 300);

            nodes = [];
            links = [];
            nodes = ind[k].nodes;
            links = ind[k].links;

      var link = svgSUBS.selectAll(".linkSUB")
          .data(ind[k].links)
          .enter().append("g")
          .attr("class", "linkSUB");
           link.append("line")
          .style("stroke-width", function(d) { return (d.bond * 2 - 1) * 2 + "px"; });

      link.filter(function(d) { return d.bond > 1; }).append("line")
          .attr("class", "separator");

      var node = svgSUBS.selectAll(".nodeSUB")
          .data(ind[k].nodes)
          .enter().append("g")
          .attr("class", "nodeSUB")
          .call(d3.layout.force()
                .size([width, height])
                .charge(-400)
                .linkDistance(function(d) { return radius + 40;}).drag);

      node.append("circle")
          .attr("r", radius)
          .style("fill", function(d) { return color(d.Node); });

      node.append("text")
          .attr("dy", ".35em")
          .attr("text-anchor", "middle")
          .text(function(d) { return d.Node + d.label; });
              function tick() {
        link.selectAll("line")
            .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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
      }
      d3.layout.force()
                .size([width, height])
                .charge(-400)
                .linkDistance(function(d) { return radius + 40;})
                .nodes(nodes)
                .links(links)
                .on("tick", tick)
                .start();


            }                                      
    }   
    });
}

The result I get after execution is as follows: graphs

The JSON file contains multiple graph data formatted as follows:

[{
 "subgraph": "21",
 "nodes": [
{"Node": "0", "label": "N"},
{"Node": "1", "label": "N"},
{"Node": "2", "label": "C"},
{"Node": "3", "label": "C"},
{"Node": "4", "label": "C"}
],
"links": [
{"source":4, "target":0, "bond":1},
{"source":2, "target":1, "bond":1},
{"source":3, "target":2, "bond":1},
{"source":4, "target":3, "bond":1}
],
"graphs": [
{"graph": "1 HMDB00001"},
{"graph": "2 HMDB00002"},
{"graph": "2 HMDB00002"}
]},
{
 "subgraph": "22",
 "nodes": [
{"Node": "0", "label": "N"},
{"Node": "1", "label": "C"},
{"Node": "2", "label": "C"},
{"Node": "3", "label": "C"}
],
"links": [
{"source":1, "target":0, "bond":1},
{"source":2, "target":1, "bond":1},
{"source":3, "target":2, "bond":1}
],
"graphs": [
{"graph": "1 HMDB00001"},
{"graph": "2 HMDB00002"},
{"graph": "2 HMDB00002"}
]},
..........
........

I can't figure out why only the last graph is appearing properly and the force layout is working only for that graph.

Upvotes: 1

Views: 816

Answers (1)

arianit
arianit

Reputation: 107

I found the solution, using "forEach(function (k)" instead of "for (k in ind)" loop did the work. Seems that the latter executes the functions only for the last element of the loop. The complete code used:

//button click 
function updateData() {
    var selected_graph = $("#select-list option:selected").text();

    d3.json("out_graph.json", function(subgraphs, ID) {
    ID.forEach(function (k) {
        var k_data = k.graphs;
        if (k_data.values = selected_graph)
            {
            console.log(k_data.values ); //works
            console.log(k);
    var svgSUBS = d3.select("#subgraphs").append("svg")
                            .attr("id","subsID")
                            .attr("width", 300)
                            .attr("height", 300);

      var forceSUB = d3.layout.force()
                .size([width, height])
                .charge(-400)
                .linkDistance(function(d) { return radius + 40;});

      var link = svgSUBS.selectAll(".linkSUB")
          .data(k.links)
          .enter().append("g")
          .attr("class", "linkSUB");
           link.append("line")
          .style("stroke-width", function(d) { return (d.bond * 2 - 1) * 2 + "px"; });

      link.filter(function(d) { return d.bond > 1; }).append("line")
          .attr("class", "separator");

      var node = svgSUBS.selectAll(".nodeSUB")
          .data(k.nodes)
          .enter().append("g")
          .attr("class", "nodeSUB")
          .call(forceSUB.drag);

      node.append("circle")
          .attr("r", radius)
          .style("fill", function(d) { return color(d.Node); });

      node.append("text")
          .attr("dy", ".35em")
          .attr("text-anchor", "middle")
          .text(function(d) { return d.Node + d.label; });
              function tick() {
        link.selectAll("line")
            .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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
      }
            forceSUB
                .nodes(k.nodes)
                .links(k.links)
                .on("tick", tick)
                .start();
            }                                      
    }); 
    });
}

Upvotes: 3

Related Questions