从嵌套结构递归映射 3d.js 图形节点和链接

时间:2021-05-19 15:46:15

标签: javascript arrays sorting d3.js graph

需要一种优雅的方式来映射节点和链接,为 d3.js 力图做好准备。我尝试使用 lodash 但找不到方法。我需要的是将所有嵌套对象提取到单个级别的新数组中,并且对于每个对象,根据其深层索引,生成具有源和目标属性的新链接数组...例如:如果一个对象有 2 个孩子,我需要生成 2 个链接,其中“源”是父 ID,“目标”是它本身的 ID。

这是我的输入结构:

[
   {
      "id": 0,
      "name":"Name0",
      "linkType":"PROFESSIONAL",
      "children":[
         {
            "id": 1,
            "name":"Name1",
            "linkType":"FAMILY",
            "children":[
               {
                  "id": 2,
                  "name":"Name2",
                  "linkType":"FAMILY",
                  "children":[
                     {
                        "id": 3,
                        "name":"Name3",
                        "linkType":"FAMILY"
                     },
                     {
                        "id": 4,
                        "name":"Name4",
                        "linkType":"FAMILY"
                     }
                  ]
               },
               {
                  "id": 5,
                  "name":"Name5",
                  "linkType":"FAMILY"
               }
            ]
         },
         {
            "id": 6,
            "name":"Name6",
            "linkType":"FAMILY"
         }
      ]
   },
   {
    "id": 7,
    "name":"Name7",
    "linkType":"PROFESSIONAL",
    "children":[
       {
          "id": 8,
          "name":"Name8",
          "linkType":"FAMILY",
          "children":[
             {
                "id": 9,
                "name":"Name9",
                "linkType":"FAMILY"
             },
             {
                "id": 10,
                "name":"Name10",
                "linkType":"FAMILY"
             }
          ]
       },
       {
          "id": 11,
          "name":"Name11",
          "linkType":"FAMILY",
          "children":[
            {
               "id": 12,
               "name":"Name12",
               "linkType":"FAMILY",
               "children":[
                  {
                     "id": 13,
                     "name":"Name13",
                     "linkType":"FAMILY"
                  },
                  {
                     "id": 14,
                     "name":"Name14",
                     "linkType":"FAMILY"
                  }
               ]
            },
            {
               "id": 15,
               "name":"Name15",
               "linkType":"FAMILY"
            }
         ]
       }
    ]
  }
]

输出应该是: enter image description here

结果数组应该是:

const nodes = [ //no matter the deep index... all the nodes will be on the same array
     { 
        "name":"Name0",
        "linkType":"PROFESSIONAL",
     },
     {
        "name":"Name7",
        "linkType":"PROFESSIONAL",
     },
     {
        "name":"Name1",
        "linkType":"FAMILY",
     }
     .
     .
     .
]

const links = [ 
    {
        id: 0, //first generated link
        source: 0 // the source node id
        target: 1 // the target node id -- node Name0 is linked with node Name1
    },
    {
        id: 1,
        source: 0
        target: 2
    },
    {
        id: 2,
        source: 1
        target: 2
    }
    .
    .
    .
]

1 个答案:

答案 0 :(得分:1)

您可以使用 d3.hierarchy 和 node.descendants 来获取给定根(包括该根)的所有节点。然后,您只需要获取相关数据,并为每个子项在该子项与其父项之间创建一个链接。

数组中有多个图形会添加一个层,但至少这应该提供一些想法:

var links = [];
var nodes = [];

nested.map(function(data) {
  d3.hierarchy(data).descendants().forEach(function(node) {
    if(node.children) node.children.forEach(function(child) {
        links.push({
          target: node.data.id,
          source: child.data.id
        })
      })  

    nodes.push({
      id: node.data.id,
      name: node.data.id,
      linkType: node.data.linkType    
    })
 })
})

var nested = [
   {
      "id": 0,
      "name":"Name0",
      "linkType":"PROFESSIONAL",
      "children":[
         {
            "id": 1,
            "name":"Name1",
            "linkType":"FAMILY",
            "children":[
               {
                  "id": 2,
                  "name":"Name2",
                  "linkType":"FAMILY",
                  "children":[
                     {
                        "id": 3,
                        "name":"Name3",
                        "linkType":"FAMILY"
                     },
                     {
                        "id": 4,
                        "name":"Name4",
                        "linkType":"FAMILY"
                     }
                  ]
               },
               {
                  "id": 5,
                  "name":"Name5",
                  "linkType":"FAMILY"
               }
            ]
         },
         {
            "id": 6,
            "name":"Name6",
            "linkType":"FAMILY"
         }
      ]
   },
   {
    "id": 7,
    "name":"Name7",
    "linkType":"PROFESSIONAL",
    "children":[
       {
          "id": 8,
          "name":"Name8",
          "linkType":"FAMILY",
          "children":[
             {
                "id": 9,
                "name":"Name9",
                "linkType":"FAMILY"
             },
             {
                "id": 10,
                "name":"Name10",
                "linkType":"FAMILY"
             }
          ]
       },
       {
          "id": 11,
          "name":"Name11",
          "linkType":"FAMILY",
          "children":[
            {
               "id": 12,
               "name":"Name12",
               "linkType":"FAMILY",
               "children":[
                  {
                     "id": 13,
                     "name":"Name13",
                     "linkType":"FAMILY"
                  },
                  {
                     "id": 14,
                     "name":"Name14",
                     "linkType":"FAMILY"
                  }
               ]
            },
            {
               "id": 15,
               "name":"Name15",
               "linkType":"FAMILY"
            }
         ]
       }
    ]
  }
]

var links = [];
var nodes = [];

nested.map(function(data) {
  d3.hierarchy(data).descendants().forEach(function(node) {
    if(node.children) node.children.forEach(function(child) {
        links.push({
          target: node.data.id,
          source: child.data.id
        })
      })  

    nodes.push({
      id: node.data.id,
      name: node.data.id,
      linkType: node.data.linkType    
    })
 })
})

console.log(links,nodes);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

相关问题