Javascript 如何在D3.js中创建蝴蝶结方法/图表?

Javascript 如何在D3.js中创建蝴蝶结方法/图表?,javascript,d3.js,Javascript,D3.js,我目前正在从事一个项目,在这个项目中,我需要根据来自应用程序的数据创建蝴蝶结图 从一些研究来看,最适合实现这一目标的图书馆是 我已经研究了这些例子: 可折叠树: 层次结构图: 下面是我想尝试和复制的一个基本蝴蝶结图示例: 正如您在图中所看到的,我需要多个顶级项目和/或一棵双树,它可以独立地打开每一侧/每棵树,数据从顶级项目的左到右(红色侧)和从右到左(蓝色侧)流动 使用D3.js可以实现吗 关于d3.js的教程只包括标准图表,如条形图和我发现只有一个顶级项目的在线树示例 如果您能提供任何正确方

我目前正在从事一个项目,在这个项目中,我需要根据来自应用程序的数据创建蝴蝶结图

从一些研究来看,最适合实现这一目标的图书馆是

我已经研究了这些例子:

可折叠树:

层次结构图:

下面是我想尝试和复制的一个基本蝴蝶结图示例:

正如您在图中所看到的,我需要多个顶级项目和/或一棵双树,它可以独立地打开每一侧/每棵树,数据从顶级项目的左到右(红色侧)和从右到左(蓝色侧)流动

使用D3.js可以实现吗

关于d3.js的教程只包括标准图表,如条形图和我发现只有一个顶级项目的在线树示例


如果您能提供任何正确方向的帮助、建议或指点,我们将不胜感激。

有一些有用的资料需要考虑:

  • -哪个链接到一个块,显示通过改变节点的x和y坐标的使用可以实现从左到右的方向
  • -公认的答案是在两个
    s中画两棵树,并将其中一棵移到“上方”
  • -v6非常有用,因为它允许
    Array.from
    d3.tree
    方法获取节点列表,而无需遍历层次结构
  • 第二个问题与您的问题不太相似,因此将第三个问题改编为使用第一个问题中的原则:

    • 你需要两棵树——一棵从根部向左向右,另一棵从根部向右向左
    • 该方法有效地计算了节点定位的右侧
      x
      s和
      y
      s(除了“水平”渲染,在每个Mike Bostock块的代码中翻转使用
      x
      y
      )。我们希望了解节点之间的相对位置,但同时在右侧树(中心位于
      g
      )和左侧树(中心位于
      g
      )上进行平移
    • 例外情况是根节点,例如,如果“左”与“右”上有更多节点,则根节点的位置将略有不同。必须为两棵树选择一个根节点
    • 可以重新计算坐标,以便:
      • 在右侧树中,应添加
        y
        坐标(现在的意思是
        x
        )的
        width/2
        ,以将其移动到
        g
        的垂直中心,然后减半以将“分支”长度保持在
        宽度范围内
      • 在左侧树中,应将
        y
        坐标(现在的意思是
        x
        )减半(与右侧树中“分支长度”的处理相同)并取反,以将节点位置翻转到根节点的左侧(您选择的位置如左侧树的根位置)
    下面是演示:

    //有用的链接
    // https://bl.ocks.org/mbostock/3184089
    // https://bl.ocks.org/d3noob/72f43406bbe9e104e957f44713b8413c
    变量treeDataL={
    “名称”:“根”,
    “儿童”:[
    {
    “名称”:“L_A_1”,
    “儿童”:[
    {“name”:“L_B_1”},
    {“名称”:“L_B_2”}
    ]
    },
    {
    “名称”:“L_A_2”,
    “儿童”:[
    {“名称”:“L_B_3”},
    {“名称”:“L_B_4”}
    ]
    }
    ]
    }
    变量treeDataR={
    “名称”:“根”,
    “儿童”:[
    {
    “名称”:“R_A_1”,
    “儿童”:[
    {“name”:“R_B_1”},
    {“name”:“R_B_2”},
    {“name”:“R_B_3”}
    ]
    },
    {
    “名称”:“R_A_2”,
    “儿童”:[
    {“name”:“R_B_3”},
    {“name”:“R_B_4”},
    {“name”:“R_B_5”},
    {“name”:“R_B_6”}
    ]
    }
    ]
    }
    //设置图表的尺寸和边距
    var margin={顶部:50,右侧:50,底部:50,左侧:50},
    宽度=400-margin.left-margin.right,
    高度=400-margin.top-margin.bottom;
    //声明树布局并指定大小
    var tree=d3.tree()
    .尺寸([宽度、高度]);
    //使用d3层次结构创建2x树
    //这是计算坐标的地方
    var nodesL=树(d3.层次结构(treeDataL));
    var nodesR=树(d3.层次结构(treeDataR));
    //获取节点数组-需要v6
    nodesLArray=Array.from(nodesL);
    nodesrray=Array.from(nodesR);
    //将nodesR root切换到nodesL
    //这里的选择是将LH树的根坐标分配给RH
    nodesLRoot=nodesLArray.find(n=>n.data.name==“根”);
    nodesRRoot=nodesRArray.find(n=>n.data.name==“根”);
    nodesroot.x=nodesLRoot.x;
    nodesroot.y=nodesLRoot.y;
    //这有点像“重要的一点”
    //记住对于水平布局,翻转x和y。。。
    //LH:将节点中的所有y减半并取反。L添加宽度/2
    nodesLArray.forEach(n=>n.y=((n.y*0.5)*-1)+宽度/2);
    //右侧:将所有y节点减半并添加宽度/2
    forEach(n=>n.y=(n.y*0.5)+宽度/2);
    //现在更接近链接3中的教程
    //追加svg
    var svg=d3.选择(“主体”)
    .append(“svg”)
    .attr(“宽度”,宽度+边距。左侧+边距。右侧)
    .attr(“高度”,高度+边距。顶部+边距。底部);
    //将g与边距对齐
    var g=svg.append(“g”)
    .attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
    //渲染两棵树
    [nodesL,nodesR].forEach(函数(节点,i){
    //添加节点之间的链接
    //需要根据索引选择链接,以防止渲染错误
    var link=g.selectAll(`links${i}`)
    .data(节点.子体().slice(1))
    .输入()
    .append(“路径”)
    .attr(“class”,link links${i}`)//注意两个类
    .attr(“d”,函数(d){
    //x和y在此处翻转以实现水平放置
    返回`M${d.y}、${d.x}C${d.y}、${(d.x+d.parent.x)/2}${d.parent.y}、${(d.x+d.parent.x)/2}${d.parent.y}、${d.parent.x}`
    });
    //将每个节点添加为一个组
    //需要根据索引选择节点,以防止渲染错误
    var node=g.selectAll(`.nodes${i}`)
    .data(节点.子体())
    .输入()
    .append(“