从多个不同的JSON数组链接D3.js Force Layout中的节点

时间:2015-01-21 02:42:18

标签: javascript json d3.js force-layout

我正在使用嵌套的JSON Feed来创建一个带有D3.js的Force Directed图。

我当前的代码查找名为' children'的子数组。并将这些数组中的所有项显示为节点。这已经有一段时间了,我很高兴。

但我现在需要为每个项目添加一些子数组。

所以我的JSON结构类似于以下内容:

{  
   "structure":[  
      {  
         "name":"Grandfather",
         "children":[  
            {  
               "name":"Father 1",
               "son":[  
                  {  
                     "name":"Son"
                  }
               ],
               "daughter":[  
                  {  
                     "name":"Daughter"
                  }
               ]
            },
            {  
               "name":"Father 2",
               "son":[  
                  {  
                     "name":"Son"
                  }
               ],
               "daughter":[  
                  {  
                     "name":"Daughter"
                  }
               ]
            }
         ]
      }
   ]
}

我希望通过这样做实现的一个目的是为不同阵列的节点提供单独的样式。

这是我想要创建的图表类型的图像。

enter image description here

这是我目前使用的D3.js代码。当只有一个名为children的子数组时,这种方法有效。

var w = 1000,
    h = 800,
    radius = 10,
    node,
    link,
    root,
    title;

 var jsonURL = 'assets/scripts/nodes.json'

d3.json(jsonURL, function(json) {
    root = json.words[0]; //set root node
    root.fixed = true;
    root.x = w / 2;
    root.y = h / 2 - 80;
    update();
});

var force = d3.layout.force()
    .on("tick", tick)
    .charge(function(d) { return -500; })
    .linkDistance(function(d) { return d.target._children ? 200 : 120; })
    .size([w, h - 160]);

var svg = d3.select(".graph").append("svg")
    .attr("width", w)
    .attr("height", h);


function update() {
    var nodes = flatten(root),
    links = d3.layout.tree().links(nodes);

    // Restart the force layout.
    force
        .nodes(nodes)
        .links(links)
        .start();

    // Update the links…
    link = svg.selectAll("line.link")
        .data(links, function(d) { return d.target.id; });

    // Enter any new links.
    link.enter().insert("svg:line", ".node")
        .attr("class", "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; });

    // Exit any old links.
    link.exit().remove();

    // Update the nodes…
    node = svg.selectAll("circle.node")
        .data(nodes, function(d) { return d.id; })
        .style("fill", "red")

    node.transition()
        .attr("r", radius);

    // Enter any new nodes.
    node.enter()
        .append("svg:circle")
        .attr("class", "node")
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; })
        .attr("r", radius)
        .style("fill", "red")
        .call(force.drag);

    // Exit any old nodes.
    node.exit().remove();

}

function tick() {
    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; });

}

// Returns a list of all nodes under the root.
function flatten(root) {
    var nodes = [], i = 0;

    function recurse(node) {
        if (node.children) node.size = node.children.reduce(function(p, v) { return p + recurse(v); }, 0);
        if (!node.id) node.id = ++i;
        nodes.push(node);
        return node.size;
    }

    root.size = recurse(root);
    return nodes;

}

据我了解,递归函数是我需要更改以查看多个数组而不仅仅是子元素。

但是我还需要将这些新节点链接到它们的父节点。

如果有人对如何做到这一点有任何想法。我将非常感激。

0 个答案:

没有答案