Javascript 在d3中选择子节点的位置

Javascript 在d3中选择子节点的位置,javascript,d3.js,Javascript,D3.js,我在运行时将节点添加到D3树布局中,但是当插入新的子节点时,原始子节点被推到最左边。我希望原始的孩子在中间(或接近)的儿童群体,以便如果图表是类似的东西: Parent Child C 添加其他节点A、B、D和E将生成如下图: Parent ChildA

我在运行时将节点添加到D3树布局中,但是当插入新的子节点时,原始子节点被推到最左边。我希望原始的孩子在中间(或接近)的儿童群体,以便如果图表是类似的东西:

                                   Parent

                                   Child C
添加其他节点A、B、D和E将生成如下图:

                                   Parent

               ChildA     ChildB   ChildC    ChildD   ChildE
与此相反:

                                   Parent

               ChildC     ChildA   ChildB    ChildD   ChildE
如果相关,此更新功能的代码如下:

function update(record_to_add, parent) {
                        if (nodes.length >= 500) return clearInterval(timer);

                        // Add a new node to a random parent.
                        var n = {id: nodes.length, Username: record_to_add.Username},
                                p = nodes[parent];
                        if (p.children) p.children.push(n); else p.children = [n];
                        nodes.push(n);

                        // Recompute the layout and data join.
                        node = node.data(tree.nodes(root), function(d) { return d.id; });
                        link = link.data(tree.links(nodes), function(d) { return d.source.id + "-" + d.target.id; });

                        nodes.forEach(function (d) {
                        });

                        // Add entering links in the parent’s old position.
                        link.enter().insert("path", ".node")
                                .attr("class", "link")
                                .attr("d", function(d) {
                                    var o = {x: d.source.px, y: d.source.py};
                                    return diagonal({source: o, target: o});
                                });
                        node.enter().insert("text")
                                .attr("x", function(d) { return (d.parent.px);})
                                .attr("y", function(d) { return (d.parent.py);})
                                .text(function(d) { return d.Username; });

                        // Add entering nodes in the parent’s old position.
                        node.enter().append("circle", "g")
                                .attr("class", "node")
                                .attr("r", 10)
                                .attr("cx", function(d) { return d.parent.px; })
                                .attr("cy", function(d) { return d.parent.py; });

                        node.on("mousedown", function (d) {
                            var g = d3.select(this); // The node
                            // The class is used to remove the additional text later
                            console.log(d.Username);
                            if (d.id == null)
                            {
                                console.log("ASDgasd");
                            }
                            else
                            {
                                try {
                                    downstream_length =
                                            DownstreamRecords[d.Username].length;
                                }
                                catch(err) {
                                    downstream_length = 0;
                                }

                                for (var i = 0; i < downstream_length; ++i)
                                {
                                    update(DownstreamRecords[d.Username][i], d.id);
                                }
                            }
                        });

                        node.on("mouseover", function (d) {
                            var g = d3.select(this); // The node
                            // The class is used to remove the additional text later
                            var info = g.append('text')
                                    .classed('info', true)
                                    .attr('x', 20)
                                    .attr('y', 10)
                                    .text('More info');
                        });

                        // Transition nodes and links to their new positions.
                        var t = svg.transition()
                                .duration(duration);

                        t.selectAll(".link")
                                .attr("d", diagonal);

                        t.selectAll(".node")
                                .attr("cx", function(d) { return d.px = d.x; })
                                .attr("cy", function(d) { return d.py = d.y; });

                        t.selectAll("text")
                                .style("fill-opacity", 1)
                                .attr("x", function(d) { return d.px = d.x + 20; })
                                .attr("y", function(d) { return d.py = d.y; });
                    }
函数更新(记录到添加,父级){
如果(nodes.length>=500)返回clearInterval(计时器);
//将新节点添加到随机父节点。
var n={id:nodes.length,Username:record_to_add.Username},
p=节点[父节点];
如果(p.children)p.children.push(n);否则p.children=[n];
节点push(n);
//重新计算布局和数据联接。
node=node.data(tree.nodes(root),函数(d){return d.id;});
link=link.data(tree.links(节点),函数(d){返回d.source.id+“-”+d.target.id;});
nodes.forEach(函数(d){
});
//在父级的旧位置添加输入链接。
link.enter().insert(“路径”,“节点”)
.attr(“类”、“链接”)
.attr(“d”,函数(d){
var o={x:d.source.px,y:d.source.py};
返回对角线({source:o,target:o});
});
node.enter().insert(“文本”)
.attr(“x”,函数(d){return(d.parent.px);})
.attr(“y”,函数(d){return(d.parent.py);})
.text(函数(d){返回d.Username;});
//在父节点的旧位置添加输入节点。
node.enter().append(“圆”、“g”)
.attr(“类”、“节点”)
.attr(“r”,10)
.attr(“cx”,函数(d){return d.parent.px;})
.attr(“cy”,函数(d){return d.parent.py;});
node.on(“mousedown”,函数(d){
var g=d3。选择(此);//节点
//该类用于以后删除附加文本
console.log(d.Username);
如果(d.id==null)
{
控制台日志(“ASDgasd”);
}
其他的
{
试一试{
下游长度=
下行记录[d.Username]。长度;
}
捕捉(错误){
下游_长度=0;
}
对于(var i=0;i<下游_长度;++i)
{
更新(下游记录[d.Username][i],d.id);
}
}
});
node.on(“鼠标悬停”,函数(d){
var g=d3。选择(此);//节点
//该类用于以后删除附加文本
var info=g.append('text')
.classed('info',true)
.attr('x',20)
.attr('y',10)
.text(“更多信息”);
});
//将节点和链接转换到其新位置。
var t=svg.transition()
.持续时间(持续时间);
t、 选择全部(“.link”)
.attr(“d”,对角线);
t、 选择全部(“.node”)
.attr(“cx”,函数(d){返回d.px=d.x;})
.attr(“cy”,函数(d){返回d.py=d.y;});
t、 选择全部(“文本”)
.style(“填充不透明度”,1)
.attr(“x”,函数(d){返回d.px=d.x+20;})
.attr(“y”,函数(d){返回d.py=d.y;});
}

而不是使用推送添加子用途

arry.splice(index, 0, newObject);
所以你们可以在你们选择的位置上添加新的子元素,但你们已经做了一些验证,比如长度、数组和索引点等

像这样

if (p.children) p.children.push(n); else p.children = [n];
换成

 if (p.children){

    p.children.splice(0, 0, n);
     // or you can do some calculation according to number of child 
      available and made index
    //p.children.push(n);
}
 else{ p.children = [n];}

您是否尝试过对节点进行排序?看,排序谓词是什么?节点没有顺序,可以是您希望它们出现的任何顺序。