D3.js 从扁平阵列绘制D3组织结构图
我想画网络营销的层次结构图。每个人有3个位置(p1、p2、p3),p1是主要位置,p1和p2可以有左右两个孩子 因此,我将从API返回的数组放平,如下所示: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":
[{
"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