2015-04-01 53 views
1

如何在D3.js包布局已经创建并显示在SVG元素中时将其他节点添加到D3.js包布局中?重新计算整个pack是一个选项,但我想插入更加无缝。将节点插入到D3包装布局中(缩放分页)

我在找的是一个pack().addNode()函数,它允许我将其他子节点插入现有的叶节点。当用户放大到该叶节点时,叶节点应该变成父节点并将插入的节点显示为子节点。

请看看at my fiddle here。名为subnode_jane的节点应接收subnode_subnodes中的孩子作为其新孩子。

var subnode_subnodes = [{ 
    "name": "JanesDaughter", 
    "size": 1030 
}, { 
    "name": "JanesSon", 
    "size": 12000 
}]; 

function zoom(d) { 
    var focus0 = focus; 
    focus = d; 

    if (d.name === "subnode_jane") { 
     alert("Oh I see subnode_jane has unpaginated children; insert them now!"); 
    } 

/* ... */ 
} 

可选:当这样做时,如果原始节点的总体外观保持完全相同将会很好。谢谢!

相关:update a layout.pack in d3.js

+1

http://bl.ocks.org/mbostock/1095795,http://stackoverflow.com/questions/11606214/adding-and -removing-nodes-in-d3js-force-graph,http://stackoverflow.com/questions/21070899/d3-js-how-to-remove-nodes-when-link-data-updates-in-a-force -布局 – 2015-04-01 10:04:15

回答

1

Please find my workaround solution here。 (解决方法,因为我无法编写D3包布局的扩展功能)

我的解决方案是创建第二个“虚拟”包,并使用它的圆形坐标集成到原始包中。适用于我。

// hard-coded function 
var virtualNodesByParentNode = function (d3NodeParentElement, nodeChildrenElementArray) { 
    root.children[0].children[0].children = subnode_subnodes; 
    // we need to do this because otherwise, the parent node object will be changed 
    var d3NodeParentElementClone = clone(d3NodeParentElement); 
    var pack = d3.layout.pack() 
     .padding(2) 
     // -1 is important to avoid edge overlap 
     .size([d3NodeParentElementClone.r * 2 - 1, d3NodeParentElementClone.r * 2 - 1]) 
     .value(function (d) { 
    return d.size; 
     }); 
    d3NodeParentElementClone.children = nodeChildrenElementArray; 
    var nodes = pack.nodes(d3NodeParentElementClone) 
    // absolute x,y coordinates calculation 
    var curChildnode; 
    for (var i = 1; i < nodes.length; i++) { 
     curChildnode = nodes[i]; 
     curChildnode.x = curChildnode.x - nodes[0].x + d3NodeParentElement.x; 
     curChildnode.y = curChildnode.y - nodes[0].y + d3NodeParentElement.y; 
     curChildnode.depth = d3NodeParentElement.depth + 1; 
     curChildnode.parent = d3NodeParentElement; 
    } 
    nodes.splice(0, 1); 
    return nodes; 
}; 

的如果zoom函数内条件:

if (d.name === "subnode_jane" && done === 0) { 
    done = 1; 
    var virtualNodes = virtualNodesByParentNode(d, subnode_subnodes); 
    d.children = virtualNodes; 
    // http://stackoverflow.com/a/5081471/2381339 
    nodes.push.apply(nodes, virtualNodes); 
    circle = svg.selectAll("circle") 
     .data(nodes) 
     .enter().append("circle") 
     .attr("class", function (d) { 
     return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; 
    }) 
     .style("fill", function (d) { 
     return "red"; 
    }) 
     .on("click", function (d) { 
     if (focus !== d) zoom(d), d3.event.stopPropagation(); 
    }); 
    text.remove(); 
    text = svg.selectAll("text") 
     .data(nodes) 
     .enter().append("text") 
     .attr("class", "label") 
     .style("fill-opacity", function (d) { 
     return d.parent === root ? 1 : 0; 
    }) 
     .style("display", function (d) { 
     return d.parent === root ? null : "none"; 
    }) 
     .text(function (d) { 
     return d.name; 
    }); 
    circle = svg.selectAll("circle"); 
    node = svg.selectAll("circle,text"); 
    // zoom to current focus again (do the transformation of the updated elements) 
    zoomTo(view); 
    return zoom(d); 
}