D3.js来自json文件的多个力布局图

时间:2015-04-11 11:35:33

标签: javascript json svg d3.js force-layout

我已经定义了以下函数,该函数从“按钮点击”中读取JSON文件中的数据,它应该生成多个d3图,每个图都在自己的svg容器中:

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


            }                                      
    }   
    });
}

执行后得到的结果如下: graphs

JSON文件包含多个格式如下的图形数据:

[{
 "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"}
]},
..........
........

我无法弄清楚为什么只有最后一个图形正确显示且力布局仅适用于该图形。

1 个答案:

答案 0 :(得分:3)

我找到了解决方案,使用“forEach(function(k)”而不是“for(k in ind)”循环完成了工作。似乎后者只为循环的最后一个元素执行函数。使用的代码:

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