D3.js 从扁平阵列绘制D3组织结构图

D3.js 从扁平阵列绘制D3组织结构图,d3.js,charts,orgchart,treechart,D3.js,Charts,Orgchart,Treechart,我想画网络营销的层次结构图。每个人有3个位置(p1、p2、p3),p1是主要位置,p1和p2可以有左右两个孩子 因此,我将从API返回的数组放平,如下所示: [{ "parentplaceid": "", "placeid": "p1_20201044", "rpoint": 0, "rsaving": 0, "status":

我想画网络营销的层次结构图。每个人有3个位置(p1、p2、p3),p1是主要位置,p1和p2可以有左右两个孩子

因此,我将从API返回的数组放平,如下所示:

    [{
  "parentplaceid": "",
  "placeid": "p1_20201044",
  "rpoint": 0,
  "rsaving": 0,
  "status": false,
  "type": "main_place",
  "lpoint": 0,
  "lsaving": 0
}, {
  "parentplaceid": "p1_20201044",
  "placeid": "p2_20201044",
  "rpoint": 0,
  "rsaving": 0,
  "status": false,
  "type": "left_place",
  "lpoint": 0,
  "lsaving": 0
}, {
  "parentplaceid": "p2_20201044",
  "placeid": "p1_20201045",
  "rpoint": 0,
  "rsaving": 0,
  "status": false,
  "type": "main_place",
  "lpoint": 0,
  "lsaving": 0
}, {
  "parentplaceid": "p1_20201045",
  "placeid": "p2_20201045",
  "rpoint": 0,
  "rsaving": 0,
  "status": false,
  "type": "left_place",
  "lpoint": 0,
  "lsaving": 0
}, {
  "parentplaceid": "p1_20201045",
  "placeid": "p3_20201045",
  "rpoint": 0,
  "rsaving": 0,
  "status": false,
  "type": "right_place",
  "lpoint": 0,
  "lsaving": 0
}, {
  "parentplaceid": "p2_20201044",
  "placeid": "p1_20201041",
  "rpoint": 0,
  "rsaving": 0,
  "status": false,
  "type": "main_place",
  "lpoint": 0,
  "lsaving": 0
}, {
  "parentplaceid": "p1_20201041",
  "placeid": "p2_20201041",
  "rpoint": 0,
  "rsaving": 0,
  "status": false,
  "type": "left_place",
  "lpoint": 0,
  "lsaving": 0
}, {
  "parentplaceid": "p1_20201041",
  "placeid": "p3_20201041",
  "rpoint": 0,
  "rsaving": 0,
  "status": false,
  "type": "right_place",
  "lpoint": 0,
  "lsaving": 0
}, {
  "parentplaceid": "p1_20201044",
  "placeid": "p3_20201044",
  "rpoint": 0,
  "rsaving": 0,
  "status": false,
  "type": "right_place",
  "lpoint": 0,
  "lsaving": 0
}]
现在我想通过D3组织结构图模块来绘制它。问题是每个数组都有一个parenId和一些子数组。我使用以下函数将扁平阵列转换为树状阵列:

     function unflatten(arr) {
      var tree = [],
        mappedArr = {},
        arrElem,
        mappedElem;

      // First map the nodes of the array to an object -> create a hash table.
      for (var i = 0, len = arr.length; i < len; i++) {
        arrElem = arr[i];
        mappedArr[arrElem.placeid] = arrElem;
        mappedArr[arrElem.placeid]["children"] = [];
      }

      for (var id in mappedArr) {
        if (mappedArr.hasOwnProperty(id)) {
          mappedElem = mappedArr[id];
          // If the element is not at the root level, add it to its parent array of children.
          if (mappedElem.parentplaceid) {
            mappedArr[mappedElem["parentplaceid"]]["children"].push(
              mappedElem
            );
          }
          // If the element is at the root level, add it to first level elements array.
          else {
            tree.push(mappedElem);
          }
        }
      }
      return tree;
    }
现在我想为每个节点设置样式,如下所示:

 this.data = unflatten(this.placesArray).map((d: any) => {
      const width = 350; //Math.round(Math.random()*50+300);
      const height = 160; // Math.round(Math.random()*20+130);
      const cornerShape = "ROUNDED"; //['ORIGINAL','ROUNDED','CIRCLE']
      const nodeImageWidth = 100;
      const nodeImageHeight = 100;
      const centerTopDistance = 0;
      const centerLeftDistance = 0;
      const expanded = false; //d.id=="O-6"

      const titleMarginLeft = nodeImageWidth / 2 + 20 + centerLeftDistance;
      const titleMarginRight = 20 + centerLeftDistance;

      const contentMarginLeft = width / 2 + 25;
      const contentMarginRight = 25;

      return {
        nodeId: d.placeid,
        parentNodeId: d.parentplaceid,
        width: width,
        height: height,

        borderWidth: 5,
        borderRadius: 20,
        borderColor: {
          red: 50,
          green: 0,
          blue: 0,
          alpha: 0.7
        },
        backgroundColor: {
          red: 247,
          green: 247,
          blue: 249,
          alpha: 0.4
        },
        nodeIcon: {
          size: 50
        },
        // nodeImage: {
        //   url: d.imageUrl,
        //   width: nodeImageWidth,
        //   height: nodeImageHeight,
        //   centerTopDistance: 66,
        //   centerLeftDistance: 66,
        //   cornerShape: "CIRCLE", // ORIGINAL,CIRCLE
        //   shadow: false,
        //   borderWidth: 0,
        //   borderColor: {
        //     red: 19,
        //     green: 123,
        //     blue: 128,
        //     alpha: 0,
        //   },
        // },
        person: "person info",
        template: `<div style="color:#fff;height:160px; border-radius:20px; margin-top:-30px;background-image: linear-gradient(to right, #1A464E, #1A464E);">
                    <div style="margin-left:${titleMarginLeft + 77}px;
                    margin-right:${titleMarginRight}px;
                                margin-top:30px;
                                padding-top:20px;
                                font-size:20px;
                                font-weight:bold;
                           ">${d?.parentplaceid} </div>
                   <div style="margin-left:${titleMarginLeft + 77}px;
                   margin-right:${titleMarginRight}px;
                                margin-top:3px;
                                font-size:16px;
                           ">${d?.lpoint} </div>

                   <div style="margin-left:${titleMarginLeft + 77}px;
                   margin-right:${titleMarginRight}px;
                                margin-top:3px;
                                font-size:14px;
                           ">${d?.lsaving}</div>

                   <div style="margin-left:${contentMarginLeft + 70}px;
                   margin-right:${contentMarginRight}px;
                               margin-top:15px;
                               font-size:13px;
                               position:absolute;
                               bottom:5px;
                              ">
                        <div>${d?.rpoint}</div>
                        <div style="margin-top:5px">${d?.type}</div>
                   </div>
                </div>`,
        connectorLineColor: {
          red: 0,
          green: 255,
          blue: 0,
          alpha: 1
        },
        connectorLineWidth: 5,
        dashArray: "",
        expanded: expanded
      };
    });
  });
但是我得到了以下错误:

ERROR TypeError: Cannot read property 'forEach' of undefined
问题在哪里

注意:我也使用了stratify(),但问题仍然存在

 this.chart = new TreeChart();
 if (!this.data) {
      return;
    }
    if (!this.chart) {
      return;
    }
    this.chart
      .container(this.chartContainer.nativeElement)
      .data(this.data)
      .svgWidth(500)
      .initialZoom(0.6)

      .onNodeClick(d => {
     
      })
      .render();
ERROR TypeError: Cannot read property 'forEach' of undefined