- 实现一个关联图,关联图节点的位置需要通过js计算获取,再用线连接。
实现过程
1.使用平均计算
- 先将数据进行分层
traverse(data, level, levelArr) {
if (!levelArr[level]) {
levelArr[level] = [data]
} else {
levelArr[level].push(data)
}
if (data.children) {
++level
data.children.forEach((item) => {
this.traverse(item, level, levelArr)
})
}
return levelArr
}
- 再通过分层计算x,y的位置
processData(data, width, height) {
let tData = this.traverse(data, 0, [])
let dataSet = []
const wGap = Math.round(width / tData.levelArr.length + 1)
tData.levelArr.forEach((nodes, setIndex) => {
let hGap = Math.round(height / nodes.length)
nodes.forEach((node, index) => {
node.position = {
x: wGap * setIndex + 10,
y: hGap * index +10,
}
})
})
}
- 得到的结果:

2.通过父节点分块计算
- 通过记录父节点的hGap,将父子关系想象成一个盒子,层层嵌套。

- 与第一种方法相同,先将数据分层。
- 通过父节点的hGap,再计算y。
processData(data, width, height) {
let tData = this.traverse(data, 0, [])
let dataSet = []
const wGap = Math.round(width / tData.levelArr.length + 1)
tData.levelArr.forEach((nodes, setIndex) => {
let hGap = 0
if (setIndex === 0) {
hGap = Math.round(height / nodes.length)
}
dataSet.push(...nodes)
nodes.forEach((node, index) => {
let pNode = null
let cIndex = 0
if (node.parentId !== -1) {
pNode = dataSet.find((item) => item.id === node.parentId)
hGap = pNode.position.hGap / pNode.children.length
cIndex = pNode.children.findIndex((item) => item.id === node.id)
}
node.position = {
x: wGap * setIndex + 10,
y: pNode ? pNode.position.y + hGap * cIndex : hGap * index,
hGap: hGap,
}
})
})
}
- 计算结果

- 缺点:因为容器是确定的height,当子节点过多时会被覆盖。
3.子节点累计成为块
- 思路与2一致,将父子关系想象成盒子。与2不同的是,方法3是通过累计子节点的高度形成盒子的高度,而2是固定高度进行计算。
- 与第一种方法相同,先将数据分层,计算出x坐标。
- 递归数据,通过父子关系与子节点累计,计算出y坐标。
calY(data, value) {
data.position = { y: value }
if (!data.children) {
return { data, value }
}
data.children.forEach((item, index) => {
if (index > 0) {
value += 50
}
const obj = this.calY(item, value)
value = obj.value
})
return { data, value }
},
- 计算结果