如何在d3.js树中动态添加、编辑、删除节点到树中

如何在d3.js树中动态添加、编辑、删除节点到树中,d3.js,D3.js,我是D3.js新手,我使用的是D3.js树,我想动态添加、编辑、删除节点,而不是预定义的树 这是我正在使用的代码 var json= { “名称”:“基础”, “儿童”:[ { “名称”:“类型A”, “儿童”:[ { “名称”:“第1节”, “儿童”:[ {“name”:“Child 1”}, {“name”:“Child 2”}, {“名称”:“子3”} ] }, { “名称”:“第2节”, “儿童”:[ {“name”:“Child 1”}, {“name”:“Child 2”}, {“

我是D3.js新手,我使用的是D3.js树,我想动态添加、编辑、删除节点,而不是预定义的树

这是我正在使用的代码

var json=
{
“名称”:“基础”,
“儿童”:[
{
“名称”:“类型A”,
“儿童”:[
{
“名称”:“第1节”,
“儿童”:[
{“name”:“Child 1”},
{“name”:“Child 2”},
{“名称”:“子3”}
]
},
{
“名称”:“第2节”,
“儿童”:[
{“name”:“Child 1”},
{“name”:“Child 2”},
{“名称”:“子3”}
]
}
]
},
{
“名称”:“类型B”,
“儿童”:[
{
“名称”:“第1节”,
“儿童”:[
{“name”:“Child 1”},
{“name”:“Child 2”},
{“名称”:“子3”}
]
},
{
“名称”:“第2节”,
“儿童”:[
{“name”:“Child 1”},
{“name”:“Child 2”},
{“名称”:“子3”}
]
}
]
}
]
};
var宽度=700;
var高度=650;
var maxLabel=150;
var持续时间=500;
var半径=5;
var i=0;
变种根;
var tree=d3.layout.tree()
.尺寸([高度、宽度]);
var diagonal=d3.svg.diagonal()
.投影(函数(d){返回[d.y,d.x];});
var svg=d3.选择(“正文”).追加(“svg”)
.attr(“宽度”,宽度)
.attr(“高度”,高度)
.附加(“g”)
.attr(“transform”,“translate”(+maxLabel+”,0)”);
root=json;
root.x0=高度/2;
root.y0=0;
根。子。forEach(塌陷);
函数更新(源)
{
//计算新的树布局。
var nodes=tree.nodes(root.reverse();
var links=tree.links(节点);
//为固定深度进行规格化。
forEach(函数(d){d.y=d.depth*maxLabel;});
//更新节点…
var node=svg.selectAll(“g.node”)
.数据(节点,函数(d){
返回d.id | |(d.id=++i);
});
//在父节点的上一个位置输入任何新节点。
var nodeEnter=node.enter()
.附加(“g”)
.attr(“类”、“节点”)
.attr(“transform”,函数(d){return“translate”(“+source.y0+”,“+source.x0+”));})
。开启(“点击”,点击);
nodeEnter.append(“圆”)
.attr(“r”,0)
.style(“填充”,函数(d){
返回d.(儿童?)浅蓝色“:“白色”;
});
nodeEnter.append(“文本”)
.attr(“x”,函数(d){
var间距=计算半径(d)+5;
返回d.children | | d.| children?-间距:间距;
})
.attr(“dy”,“3”)
.attr(“文本锚定”,函数(d){return d.children | | d.| u children?“end”:“start”})
.text(函数(d){返回d.name;})
.style(“填充不透明度”,0);
//将节点转换到其新位置。
var nodeUpdate=node.transition()
.持续时间(持续时间)
.attr(“转换”,函数(d){return“translate”(+d.y+),“+d.x+”);});
节点更新。选择(“圆圈”)
.attr(“r”,函数(d){return computeRadius(d);})
.style(“fill”,函数(d){return d._children?“lightsteelblue”:“fff”});
nodeUpdate.select(“文本”).style(“填充不透明度”,1);
//将退出节点转换到父节点的新位置。
var nodeExit=node.exit().transition()
.持续时间(持续时间)
.attr(“transform”,函数(d){return“translate”(“+source.y+”,“+source.x+”)”);})
.remove();
nodeExit.select(“圆圈”).attr(“r”,0);
nodeExit.select(“文本”).style(“填充不透明度”,0);
//更新链接…
var link=svg.selectAll(“path.link”)
.data(链接,函数(d){返回d.target.id;});
//在父对象的上一个位置输入任何新链接。
link.enter()插入(“路径”,“g”)
.attr(“类”、“链接”)
.attr(“d”,函数(d){
var o={x:source.x0,y:source.y0};
返回对角线({source:o,target:o});
});
//过渡链接到他们的新位置。
link.transition()
.持续时间(持续时间)
.attr(“d”,对角线);
//将退出节点转换到父节点的新位置。
link.exit().transition()
.持续时间(持续时间)
.attr(“d”,函数(d){
var o={x:source.x,y:source.y};
返回对角线({source:o,target:o});
})
.remove();
//将旧位置隐藏起来,以便过渡。
nodes.forEach(函数(d){
d、 x0=d.x;
d、 y0=d.y;
});
}
功能计算机(d)
{
if(d.children | | d.| u children)返回半径+(半径*nbEndNodes(d)/10);
否则返回半径;
}
函数nbEndNodes(n)
{
nb=0;
如果(儿童){
n、 children.forEach(函数(c){
nb+=nbEndNodes(c);
});
}
else if(n._儿童){
n、 _children.forEach(函数(c){
nb+=nbEndNodes(c);
});
}
else-nb++;
返回nb;
}
功能点击(d)
{
如果(d.儿童){
d、 _children=d.children;
d、 children=null;
} 
否则{
d、 儿童=d.\U儿童;
d、 _children=null;
}
更新(d);
}
功能崩溃(d){
如果(d.儿童){
d、 _children=d.children;
d、 _儿童。forEach(崩溃);
d、 children=null;
}
}
更新(根)
html{
字体:10px无衬线;
}
svg{
边框:1px纯银;
}
.节点{
光标:指针;
}
.节点圆{
笔画:钢蓝;
笔划宽度: