Javascript 子流程中的ed也应指向下方。

Javascript 子流程中的ed也应指向下方。,javascript,d3.js,Javascript,D3.js,新答案 昨晚考虑到这一点,我决定我天真的方法是使用黑客和蛮力。问题在于,通过引入第二个子进程数组(子进程数组)并直接放置这些节点,您将失去d3.tree的魔力。您将失去它遍历父/子关系和确定链接结构的能力。相反,我建议您保留单个子进程数组,并使用附加属性将其标记为子进程。数据结构如下所示: var treeData = { "name": "File 1", "children": [{ "name": "File 2", "children": [{ "na

新答案

昨晚考虑到这一点,我决定我天真的方法是使用黑客和蛮力。问题在于,通过引入第二个子进程数组(子进程数组)并直接放置这些节点,您将失去
d3.tree
的魔力。您将失去它遍历父/子关系和确定链接结构的能力。相反,我建议您保留单个子进程数组,并使用附加属性将其标记为子进程。数据结构如下所示:

var treeData = {
  "name": "File 1",
  "children": [{
    "name": "File 2",
    "children": [{
      "name": "File 3",
      "children": [{
        "name": "File 5"
      }, {
        "name": "File 4",
        "type": "subprocess", //<-- this is a subprocess with children
        "children": [{
          "name": "File 6"
        }]
      }]
    }]
  }]
};
完成此处理后,您可以“固定”d3.tree生成的坐标,以创建直角结构:

  nodes.forEach(function(d) {

    d.y = d.depth * 180;

    if (d.parent) {
      d.x = d.parent.x;
    }

    if (d.data.depthToSub) {
      d.y = d.parent.y;
      d.x = (d.data.depthToSub * nodes[0].x) + nodes[0].x;
    }
  });
然后,图形将使用与以前相同的代码。下面是一个运行示例:


.节点圆{
填充:#fff;
笔画:钢蓝;
笔画宽度:3px;
}
.节点文本{
字体:12px无衬线;
}
.链接{
填充:无;
冲程:#ccc;
笔画宽度:2px;
}
.阿罗{
填充:无;
冲程:#ccc;
笔画宽度:1px;
}
变量treeData={
“名称”:“文件1”,
“儿童”:[{
“名称”:“文件2”,
“儿童”:[{
“名称”:“文件3”,
“儿童”:[{
“名称”:“文件5”
}, {
“名称”:“文件4”,
“类型”:“子流程”,
“儿童”:[{
“名称”:“文件6”,
“儿童”:[{
“名称”:“文件7”
}]
}]
}]
}]
}]
};
//设置图表的尺寸和边距
var保证金={
排名:0,
右:90,,
底数:30,
左:25
},
宽度=800-边距.左-边距.右,
高度=800-margin.top-margin.bottom;
//将svg对象附加到页面主体
//将“组”元素附加到“svg”
//将“组”元素移动到左上角
var svg=d3.选择(“正文”).追加(“svg”)
.attr(“宽度”,宽度+边距。右侧+边距。左侧)
.attr(“高度”,高度+边距。顶部+边距。底部)
.附加(“g”)
.attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
var defs=svg.append(“defs”);
蔑视
.附加(“标记”)
.attr(“id”、“箭头”)
.attr(“类”、“箭头”)
.attr(“视图框”,“0-4 10”)
.attr(“参考文献”,第12页)
.attr(“参考文献”,0)
.attr(“markerWidth”,12)
.attr(“markerHeight”,12)
.attr(“方向”、“自动”)
.append(“路径”)
.attr(“d”,“M0,-4L8,0L0,4”);
var i=0,
duration=750,//转换之间的时间(交互)
根;
//声明树布局并指定大小
var treemap=d3.tree().size([200,width]);
//指定父对象、子对象、高度和深度
根=d3.层次结构(树形数据,函数(d){
返回d.儿童;
});
root.x0=0;
root.y0=0;
root.data['depthToSub']=0;
isChildOfProcess(root.children,0);
//在第二层之后崩溃
根。子。forEach(塌陷);
函数IsChildOffProcess(子级,深度){
儿童。forEach(功能(d){
d、 数据['depthToSub']=深度;
if(d.data.type&&d.data.type==“子流程”){
d、 数据['depthToSub']=1;
isChildOfProcess(d.儿童,2);
}else if(深度>0&&d.children){
isChildOfProcess(d.children,++深度);
}否则,如果(d.儿童){
isChildOfProcess(d.children,0);
}
})
}
//在第二层之后崩溃
根。子。forEach(塌陷);
更新(根);
//折叠节点及其所有子节点
功能崩溃(d){
如果(d.儿童){
d、 _children=d.children
d、 _儿童。forEach(崩溃)
d、 children=null
}
}
函数更新(源){
//为节点指定x和y位置
var treeData=树映射(根);
//计算新的树布局。
var nodes=treeData.subjects(),
links=treeData.subjects().slice(1);
nodes.forEach(函数(d){
d、 y=d.深度*180;
如果(d.父母){
d、 x=d.parent.x;
}
if(d.data.depthToSub){
d、 y=d.parent.y;
d、 x=(d.data.depthToSub*节点[0].x)+节点[0].x;
}
});
//*******************节点部分***************************
//更新节点。。。
var node=svg.selectAll('g.node')
.数据(节点、功能(d){
返回d.id | |(d.id=++i);
});
//在父对象的上一个位置输入任何新模式。
var nodeEnter=node.enter().append('g')
.attr('类','节点')
.attr(“转换”,函数(d){
返回“translate”(“+source.y0+”,“+source.x0+”);
})
.on('点击',点击);
//为节点添加圆
nodeEnter.append('circle'))
.attr('类','节点')
.attr('r',1e-6)
.样式(“填充”,功能(d){
返回d.#儿童?“淡蓝色”:“fff”;
});
//为节点添加标签
nodeEnter.append('text')
.attr(“dy”,“2em”)
.attr(“x”,函数(d){
返回d.children | | d.| U children?13:13;
})
.attr(“文本锚定”,函数(d){
返回d.children | d.| u children?“开始”:“开始”;
})
.文本(功能(d){
返回d.data.name;
});
//更新
var nodeUpdate=nodenter.merge(节点);
//转换到节点的正确位置
nodeUpdate.transition()
.持续时间(持续时间)
.attr(“转换”,函数(d){
返回“translate”(“+d.y+”,“+d.x+”);
});
//更新节点属性和样式
nodeUpdate.select('circle.node')
.attr('r',10)
.风格(“填充”,有趣
root.data['depthToSub'] = 0;
isChildOfProcess(root.children, 0);

// Collapse after the second level
root.children.forEach(collapse);

function isChildOfProcess(children, depth) {
  children.forEach(function(d) {
    d.data['depthToSub'] = depth;
    if (d.data.type && d.data.type === "subprocess") {
      d.data['depthToSub'] = 1;
      isChildOfProcess(d.children, 2);
    } else if (depth > 0 && d.children) {
      isChildOfProcess(d.children, ++depth);
    } else if (d.children) {
      isChildOfProcess(d.children, 0);
    }
  })
}
  nodes.forEach(function(d) {

    d.y = d.depth * 180;

    if (d.parent) {
      d.x = d.parent.x;
    }

    if (d.data.depthToSub) {
      d.y = d.parent.y;
      d.x = (d.data.depthToSub * nodes[0].x) + nodes[0].x;
    }
  });