D3.js 意外的d3 v4树行为

D3.js 意外的d3 v4树行为,d3.js,D3.js,下面的d3.js(v4)交互式树布局是我为用户界面项目提供的概念证明,但它的性能并没有达到预期。这是我的第一次d3.js可视化,我仍然在思考所有的概念 本质上,单击任何黄色节点都会生成两个黄色子节点(&链接)。当遵循从左到右、从上到下的单击顺序时,此操作效果良好,否则将显示意外行为 通过一个示例可能是最简单的,下面是一个片段: var数据={ 资料来源:{ 类型:“数据源”, 名称:'数据源', 筒仓:[ {name:'Silo 1',所选:true}, {name:'Silo 2',所选:fa

下面的d3.js(v4)交互式树布局是我为用户界面项目提供的概念证明,但它的性能并没有达到预期。这是我的第一次d3.js可视化,我仍然在思考所有的概念

本质上,单击任何黄色节点都会生成两个黄色子节点(&链接)。当遵循从左到右、从上到下的单击顺序时,此操作效果良好,否则将显示意外行为

通过一个示例可能是最简单的,下面是一个片段:
var数据={
资料来源:{
类型:“数据源”,
名称:'数据源',
筒仓:[
{name:'Silo 1',所选:true},
{name:'Silo 2',所选:false},
{name:'Silo 3',selected:false}
],
工会:{
类型:“联合”,
名称:'联合',
计数:空,
基数:[
{类型:'cardinality',正值:false,名称:'false',计数:40,基数:[]},
{类型:'cardinality',正:true,名称:'Truthy',计数:60,基数:[]}
]
}
}
}
//全局变量
var=20;
var container=d3.select(“#container”).style('padding',containeradding+'px');//包含结构化搜索svg
var svg=container.select('svg');//显示结构化搜索的画布
var group=svg.append('g');//包含树元素(节点和链接)
变量节点宽度=40,节点高度=30,节点间距=3,垂直节点间距=150,过渡持续时间=600;
var tree=d3.tree().nodeSize([nodeWidth,nodeHeight]);
var源;
函数nodeClicked(d){
来源=d;
开关(d.data.type){
案例“数据源”:
//todo:显示数据源弹出窗口并更新所选值
d、 data.silos[0]。所选=!d.data.silos[0]。所选;
打破
违约:
//todo:显示操作弹出窗口并更新所选值
if(d.data.cardinalies&&d.data.cardinalies.length){
d、 数据基数拼接(-2,2);
}
否则{
d、 data.cardinalites.push({type:'cardinality',positive:false,name:'F'+(new Date()).getSeconds(),count:40,cardinalites:[]});
d、 push({type:'cardinality',positive:true,name:'T'+(new Date()).getSeconds(),count:60,cardinalites:[]});
}
打破
}
render();
}
函数renderLink(源、目标){
var x=目的地x+节点宽度/2;
var y=destination.y;
var px=源.x+节点宽度/2;
var py=source.y+nodeHeight;
返回'M'+x+','+y
+‘C’+x+’,‘+(y+py)/2
+“+x+”,“+(y+py)/2
+“+px+”,“+py;
}
函数render(){
//将数据源映射到d3.tree所需的继承人权限
//d3.tree实例需要以特定方式结构化数据,以生成所需的节点和链接布局(线)
var hierarchy=d3.hierarchy(数据源,函数(d){
开关(d型){
案例“数据源”:
返回d.silos.some(函数(e){returne e.selected;})?[d.union]:未定义;
违约:
返回d.基数;
}
});
//设置布局参数(调整大小时需要所有参数)
var containerBoundingRect=container.node().getBoundingClientRect();
var width=containerBoundingRect.width-containerPadding*2;
变量高度=垂直节点分离*hierarchy.height;
svg.transition().duration(transitionDuration).attr('width',width).attr('height',height+nodeHeight);
树的大小([宽度-节点宽度,高度]);
//tree()将(x,y)坐标、深度等指定给层次结构中的节点
树(层次);
//得到后代
var subjects=hierarchy.subjects();
//存储以前的位置以进行转换
forEach(函数(d){
d、 x0=d.x;
d、 y0=d.y;
});
//确保在第一次渲染时设置了源(hierarch是根,与子体[0]相同)
源=源| |层次结构;
//渲染节点
var nodesUpdate=group.selectAll('.node').data(子体);
var nodesEnter=nodesUpdate.enter()
.append('g')
.attr('类','节点')
.attr('transform','translate('+source.x0+','+source.y0+'))
.style('opacity',0)
.on('单击',无需单击);
nodesEnter.append('rect')
.attr('rx',nodeCornerRadius)
.attr('width',nodeWidth)
.attr(“高度”,节点高度)
.attr('class',函数(d){return'box'+d.data.type;});
nodesEnter.append('text')
.attr('dx',节点宽度/2+5)
.attr('dy',函数(d){返回d.parent?-5:nodeHeight+15;})
.text(函数(d){返回d.data.name;});
节点更新
.merge(节点中心)
.transition().duration(transitionDuration)
.attr('transform',函数(d){return'translate('+d.x+','+d.y+');})
.style('opacity',1);
NodeUpdate.exit().transition().duration(transitionDuration)
.attr('transform',函数(d){return'translate('+source.x+','+source.y+');})
.style('opacity',0)
.remove();
//渲染链接
var linksUpdate=group.selectAll('.link').data(subjects.slice(1));
var linksEnter=linksUpdate.enter()
.append('路径')
.attr('class','link')
.classed('false',函数(d){返回d.data.positive==false})
.classed('truthy',函数(d){返回d.data.positive==true})
.attr('d',函数(d){var o={x:source.x0,y:source.y0};返回renderLink(o,o);})
.style('opacity',0);
链接日期
var nodesUpdate = group.selectAll('.node')
    .data(descendants, function(d){ return d.data.name});