<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#container {
width: 90vw;
height: 90vh;
position: relative;
}
.item {
width: 50px;
height: 50px;
background-color: pink;
position: absolute;
}
</style>
</head>
<body>
<div id="container">
<div class="item" id="item_1">1</div>
<div class="item" id="item_2">2</div>
<div class="item" id="item_3">3</div>
<div class="item" id="item_4">4</div>
<div class="item" id="item_5">5</div>
<div class="item" id="item_6">6</div>
<div class="item" id="item_7">7</div>
<div class="item" id="item_8">8</div>
<div class="item" id="item_9">9</div>
<div class="item" id="item_10">10</div>
<div class="item" id="item_11">11</div>
<div class="item" id="item_12">12</div>
<div class="item" id="item_13">13</div>
</div>
<script src="./01_data.js"></script>
</body>
</html>
let nodeList = [
{ id: 1 },
{ id: 2 },
{ id: 3 },
{ id: 4 },
{ id: 5 },
{ id: 6 },
{ id: 7 },
{ id: 8 },
{ id: 9 },
{ id: 10 },
{ id: 11 },
{ id: 12 },
{ id: 13 },
];
let linkList = [
{ source: 1, target: 2 },
{ source: 1, target: 8 },
{ source: 2, target: 3 },
{ source: 3, target: 4 },
{ source: 3, target: 5 },
{ source: 3, target: 6 },
{ source: 4, target: 7 },
{ source: 5, target: 7 },
{ source: 6, target: 7 },
{ source: 8, target: 9 },
{ source: 8, target: 12 },
{ source: 9, target: 10 },
{ source: 12, target: 13 },
{ source: 10, target: 11 },
{ source: 13, target: 11 },
]
let linkMap = {};
for (let i = 0; i < linkList.length; i++) {
const source = linkList[i].source;
const target = linkList[i].target;
if (linkMap[source]) {
linkMap[source].push(target);
} else {
linkMap[source] = [target]
}
if (linkMap[target]) {
linkMap[target].push(source);
} else {
linkMap[target] = [source]
}
}
let rootId = 1;
let tree = { id: 1, children: [], level: 0 }
let sameLevelNodeListMap = {
0: [tree]
};
let queue = [tree];
let visited = new Set([tree.id]);
while(queue.length > 0) {
let queueHead = queue.shift();
let queueHeadId = queueHead.id;
let adjIdList1 = linkList.filter(item => item.source === queueHeadId).map(item => item.target);
let adjIdList2 = linkList.filter(item => item.target === queueHeadId).map(item => item.source);
// let adjIdList = [...adjIdList1, ...adjIdList2];
let adjIdList = linkMap[queueHeadId];
for (let i = 0; i < adjIdList.length; i++) {
const adjId = adjIdList[i];
if (!visited.has(adjId)) {
visited.add(adjId);
let tempChild = {
id: adjId,
children: [],
level: queueHead.level + 1
};
queueHead.children.push(tempChild);
queue.push(tempChild);
if (!sameLevelNodeListMap[queueHead.level + 1]) {
sameLevelNodeListMap[queueHead.level + 1] = [tempChild]
} else {
sameLevelNodeListMap[queueHead.level + 1].push(tempChild)
}
}
}
}
console.log(tree);
console.log(sameLevelNodeListMap);
// miji
let maxBlood = 1;
tree.blood = 1;
queue = [tree];
while(queue.length > 0) {
let queueHead = queue.shift();
let childrenList = queueHead.children;
let childBlood = queueHead.blood * childrenList.length;
for (let i = 0; i < childrenList.length; i++) {
const child = childrenList[i];
child.blood = childBlood;
maxBlood = Math.max(maxBlood, childBlood);
queue.push(child);
}
}
console.log(tree);
tree.yArea = maxBlood * tree.blood;
tree.x = tree.level;
tree.y = 0;
queue = [tree];
while(queue.length > 0) {
let queueHead = queue.shift();
let childrenList = queueHead.children;
// // 推恩令
if (childrenList.length === 1) {
let onlyChild = childrenList[0];
let prevNodeList = sameLevelNodeListMap[onlyChild.level - 1];
let parentNodeList = prevNodeList.filter(item => linkMap[onlyChild.id].includes(item.id));
let sumY = parentNodeList.reduce((total, curNode) => total + curNode.y, 0);
let sumBlood = parentNodeList.reduce((total, curNode) => total + 1 / curNode.blood, 0);
onlyChild.yArea = maxBlood * sumBlood;
onlyChild.x = onlyChild.level;
onlyChild.y = sumY / parentNodeList.length;
queue.push(onlyChild);
} else {
let yUnit = queueHead.yArea / (childrenList.length + 1);
let yStart = queueHead.y + queueHead.yArea / 2;
for (let i = 0; i < childrenList.length; i++) {
const child = childrenList[i];
child.yArea = maxBlood * (queueHead.blood / childrenList.length);
child.x = child.level;
child.y = yStart - yUnit * ( i + 1);
queue.push(child);
}
}
}
console.log(sameLevelNodeListMap);
for (const level in sameLevelNodeListMap) {
if (Object.prototype.hasOwnProperty.call(sameLevelNodeListMap, level)) {
sameLevelNodeListMap[level].forEach(element => {
document.getElementById(`item_${element.id}`).style.left = element.x * 100 + 500 + 'px'
document.getElementById(`item_${element.id}`).style.top = element.y * 100 + 500 + 'px'
})
}
}