布局

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'

        })
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容