其他分享
首页 > 其他分享> > echarts 下 用关系图实现拓扑图结构(树形,星型,网状,总线,环形)

echarts 下 用关系图实现拓扑图结构(树形,星型,网状,总线,环形)

作者:互联网

树形

网状

环形

星形

总线形

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./dist/echarts.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <div style="width: 100vw;height: 100vh;"></div>
    <script>
        var data_busNodes = JSON.parse('[{ "id": "bus_0", "name": "bus_0", "value": "0", "x": 1, "y": 1, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_1", "name": "bus_1", "value": "1", "x": 300, "y": 100, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_2", "name": "bus_2", "value": "2", "x": 50000, "y": 100, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_3", "name": "bus_3", "value": "3", "x": 700, "y": 100, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_4", "name": "bus_4", "value": "4", "x": 900, "y": 100, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_5", "name": "bus_5", "value": "5", "x": 1100, "y": 100, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_6", "name": "bus_6", "value": "6", "x": 1300, "y": 100, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_7", "name": "bus_7", "value": "7", "x": 1500, "y": 100, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_8", "name": "bus_8", "value": "8", "x": 1700, "y": 100, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_9", "name": "bus_9", "value": "9", "x": 1900, "y": 100, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_10", "name": "bus_10", "value": "10", "x": 2100, "y": 100, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_11", "name": "bus_11", "value": "11", "x": 1800, "y": 400, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_12", "name": "bus_12", "value": "12", "x": 1600, "y": 400, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_13", "name": "bus_13", "value": "13", "x": 1400, "y": 400, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_14", "name": "bus_14", "value": "14", "x": 1200, "y": 400, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_15", "name": "bus_15", "value": "15", "x": 1000, "y": 400, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_16", "name": "bus_16", "value": "16", "x": 800, "y": 400, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_17", "name": "bus_17", "value": "17", "x": 600, "y": 400, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_18", "name": "bus_18", "value": "18", "x": 400, "y": 400, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }, { "id": "bus_19", "name": "bus_19", "value": "19", "x": 200, "y": 400, "label": { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }, "symbol": "image://http:a.png" }]')
        var params = [{
            id: 43,
            groupId: 5,
            entityName: '',
            entityId: '',
            entityDeviceId: 137,
            deviceParam: '{"nodeType":""}',
            deviceName: "歼-15T舰载作战飞机-006"
        }, {
            id: 44,
            groupId: 5,
            entityName: "003航母全-007",
            entityId: 137,
            entityDeviceId: 138,
            deviceParam: '{"nodeType":""}',
            deviceName: "歼-15T舰载作战飞机-006"
        }, {
            id: 52,
            groupId: 5,
            entityName: "003航母全-007",
            entityId: 137,
            entityDeviceId: 144,
            deviceParam: '{"nodeType":""}',
            deviceName: "歼-15T舰载作战飞机-006"
        }, {
            id: 45,
            groupId: 5,
            entityName: "003航母全-007",
            entityId: 137,
            entityDeviceId: 139,
            deviceParam: '{"nodeType":""}',
            deviceName: "歼-15T舰载作战飞机-006"
        }, {
            id: 46,
            groupId: 5,
            entityName: "003航母全-007",
            entityId: 139,
            entityDeviceId: 140,
            deviceParam: '{"nodeType":""}',
            deviceName: "歼-15T舰载作战飞机-006"
        }, {
            id: 47,
            groupId: 5,
            entityName: "003航母全-007",
            entityId: 139,
            entityDeviceId: 141,
            deviceParam: '{"nodeType":""}',
            deviceName: "歼-15T舰载作战飞机-006"
        }, {
            id: 48,
            groupId: 5,
            entityName: "003航母全-007",
            entityId: 141,
            entityDeviceId: 142,
            deviceParam: '{"nodeType":""}',
            deviceName: "歼-15T舰载作战飞机-006"
        }, {
            id: 49,
            groupId: 5,
            entityName: "003航母全-007",
            entityId: 141,
            entityDeviceId: 143,
            deviceParam: '{"nodeType":""}',
            deviceName: "歼-15T舰载作战飞机-006"
        }, {
            id: 50,
            groupId: 5,
            entityName: "003航母全-007",
            entityId: 138,
            entityDeviceId: 144,
            deviceParam: '{"nodeType":""}',
            deviceName: "歼-15T舰载作战飞机-006"
        }, {
            id: 51,
            groupId: 5,
            entityName: "003航母全-007",
            entityId: 138,
            entityDeviceId: 145,
            deviceParam: '{"nodeType":""}',
            deviceName: "歼-15T舰载作战飞机-006"
        }]
        function createBusNodeDatas(data_nodes, o) {
            var num = data_nodes.length
            var nodeLen = 0
            var dataNodes = []
            var dataLinks = []
            var mockBus = []
            // 制作data假节点xy
            for (i = 0; i < num; i++) {
                var x
                var y
                if (i > num / 2) {
                    x = o.x + (num - i) * 200
                    y = o.y + 400
                } else {
                    x = o.x + i * 200 + 100
                    y = o.y + 100
                }
                data_nodes[i].x = x
                data_nodes[i].y = y
                dataNodes.push(data_nodes[i])
                nodeLen++
            }
            // 制作bus假节点
            for (i = 0; i < num + 3; i++) {
                var x = o.x + i * 100
                var y = o.y + 250
                var node = {
                    id: `busNode_${i}`,
                    name: `busNode_${i}`,
                    value: `busNode_${i}`,
                    x: x,
                    y: y,
                    itemStyle: {
                        opacity: 0
                    },
                    symbolSize: 0,
                    label: {
                        normal: {
                            show: true,
                            position: 'bottom',
                            fontSize: '12'
                        }
                    },
                    symbol: 'image://http:a.png',
                }
                dataNodes.push(node)
                mockBus.push(node)
            }
            // 连接各data和bus节点
            for (let j = 0; j < num + 3; j++) {
                // console.log(dataNodes[j], mockBus[j]);
                // console.log(mockBus.filter(i => i.x === dataNodes[j].x))
                var node = mockBus.filter(i => i.x === dataNodes[j].x)[0].id
                if (j < data_nodes.length) {
                    var dataLink = {
                        source: `bus_${j}`,
                        target: node
                    }
                    dataLinks.push(dataLink)
                }
                var busLink = {
                    source: `busNode_${j}`,
                    target: `busNode_${j + 1}`
                }
                dataLinks.push(busLink)
            }
            var mockBusLen = mockBus.length
            var width = 200 * mockBusLen
            var height = 400
            return {
                dataNodes: dataNodes,
                dataLinks: dataLinks,
                width: width,
                height: height
            }
        }
        function createStarNodeDatas(data_nodes, o, radius) {
            function getNodePositon(n, r) {
                var angle = 2 * Math.PI / n
                var sumAngle = 0
                var arr = []
                for (var i = 0; i < n; i++) {
                    var x = r * Math.sin(sumAngle)
                    var y = r * Math.cos(sumAngle)
                    sumAngle += angle
                    var obj = {
                        x: x,
                        y: y
                    }
                    arr.push(obj)
                }
                return arr
            }
            var num = data_nodes.length
            var nodeLen = 0
            var dataNodes = []
            var dataLinks = []
            var mockBus = []
            var starR = radius
            // 制作data假节点
            var pointsArr = getNodePositon(num, starR)
            var node = {
                id: `starO`,
                name: `starO`,
                value: `starO`,
                x: o.x,
                y: o.y,
                itemStyle: {
                    opacity: 0
                },
                symbolSize: 0,
                label: {
                    normal: {
                        show: true,
                        position: 'bottom',
                        fontSize: '12'
                    }
                },
                symbol: 'image://http:a.png',
            }
            dataNodes.push(node)
            for (var i = 0; i < pointsArr.length; i++) {
                data_nodes[i].x = o.x + pointsArr[i].x
                data_nodes[i].y = o.y + pointsArr[i].y
                dataNodes.push(data_nodes[i])
                nodeLen++
            }

            // 连接各data节点与中心节点
            for (let j = 0; j < num; j++) {
                // 连接自己的环
                // var dataLink = {
                //     source: `${data_busNodes[j].id}`,
                //     target: `${data_busNodes[j + 1].id}`
                // }
                // dataLinks.push(dataLink)
                // 连接和中心点的环
                dataLink = {
                    source: `starO`,
                    target: `${data_nodes[j].id}`
                }
                dataLinks.push(dataLink)
            }
            // 连接起始点和终点
            // var dataLink = {
            //     source: `${data_busNodes[0].id}`,
            //     target: `${data_busNodes[num - 1].id}`
            // }
            // dataLinks.push(dataLink)

            // var mockBusLen = mockBus.length
            // var width = 200 * mockBusLen
            // var height = 400
            return {
                dataNodes: dataNodes,
                dataLinks: dataLinks,
                width: starR,
                height: starR
            }
        }
        function createRingNodeDatas(data_nodes, o, radius) {
            function getNodePositon(n, r) {
                var angle = 2 * Math.PI / n
                var sumAngle = 0
                var arr = []
                for (var i = 0; i < n; i++) {
                    var x = r * Math.sin(sumAngle)
                    var y = r * Math.cos(sumAngle)
                    sumAngle += angle
                    var obj = {
                        x: x,
                        y: y
                    }
                    arr.push(obj)
                }
                return arr
            }
            var num = data_nodes.length
            var nodeLen = 0
            var dataNodes = []
            var dataLinks = []
            var mockBus = []
            var starR = radius
            // 制作data假节点
            var pointsArr = getNodePositon(num, starR)
            var node = {
                id: `starO`,
                name: `starO`,
                value: `starO`,
                x: o.x,
                y: o.y,
                label: {
                    normal: {
                        show: true,
                        position: 'bottom',
                        fontSize: '12'
                    }
                },
                symbol: 'image://http:a.png',
            }
            dataNodes.push(node)
            for (var i = 0; i < pointsArr.length; i++) {
                data_nodes[i].x = o.x + pointsArr[i].x
                data_nodes[i].y = o.y + pointsArr[i].y
                dataNodes.push(data_nodes[i])
                nodeLen++
            }

            // 连接各data节点与中心节点
            for (let j = 0; j < num; j++) {
                // 连接自己的环
                // var dataLink = {
                //     source: `${data_busNodes[j].id}`,
                //     target: `${data_busNodes[j + 1].id}`
                // }
                // dataLinks.push(dataLink)
                // 连接和中心点的环
                dataLink = {
                    source: `starO`,
                    target: `${data_nodes[j].id}`
                }
                dataLinks.push(dataLink)
            }
            // 连接起始点和终点
            // var dataLink = {
            //     source: `${data_busNodes[0].id}`,
            //     target: `${data_busNodes[num - 1].id}`
            // }
            // dataLinks.push(dataLink)

            // 连接终点和中心点
            // var dataLink = {
            //     source: `starO`,
            //     target: `${data_busNodes[num - 1].id}`
            // }
            // dataLinks.push(dataLink)

            // var mockBusLen = mockBus.length
            // var width = 200 * mockBusLen
            // var height = 400
            return {
                dataNodes: dataNodes,
                dataLinks: dataLinks,
                width: starR,
                height: starR
            }
        }
        function createTreeNodeDatas(data_nodes, o, radius) {
            var num = data_nodes.length
            var nodeLen = 0
            var dataNodes = []
            var dataLinks = []
            var mockBus = []
            var levelArr = []
            var tree
            var flagNode = {
                node: '',
                times: 1
            }
            var levelNum = 1
            var nowRadius
            data_nodes.forEach(e => {
                e.name = e.entityDeviceId
                e.value = e.deviceName
                e.label = { "normal": { "show": true, "position": "bottom", "fontSize": "12" } }
                e.symbolSize = 20
            })
            if (data_nodes[0].entityId === '') {
                tree = data_nodes[0]
            }
            (function createTree(node, datas, level) {
                node.children = data_nodes.filter(i => i.entityId == node.entityDeviceId)
                for (var i = 0; i < node.children.length; i++) {
                    node.children[i].levelTimes = i
                }
                var levelTime = node.levelTimes// 当前层级循环的次数
                // 设置当前接节点xy坐标
                if (node.entityId === '') {
                    node.x = o.x
                    node.y = o.y
                    nowRadius = 2 * radius
                } else {
                    var levelNumber = data_nodes.filter(i => i.entityId === node.entityId).length
                    var x = data_nodes.filter(i => i.entityDeviceId === node.entityId)[0].x + (nowRadius / levelNumber) * (levelTime)
                    // - nowRadius / 2
                    var y = data_nodes.filter(i => i.entityDeviceId === node.entityId)[0].y + radius
                    node.x = x
                    node.y = y
                }
                if (node.children.length > 0) {
                    level++
                    nowRadius = nowRadius - (level - 1) * nowRadius / 5
                    node.children.forEach(i => arguments.callee(i, datas, level))
                }
            })(tree, data_nodes, 0);
            (function createLevel(node, level) {
                levelArr.push({ level: level, node: node })
                if (node.children && node.children.length > 0) {
                    level++
                    node.children.forEach(i => arguments.callee(i, level))
                }
            })(tree, 1);
            levelArr.sort(function (i, j) { return i.level - j.level });
            levelArr.forEach(element => {
                dataNodes.push(element.node)
            });
            // 连接线
            levelArr.forEach(element => {
                var node = element.node
                if (node.entityId !== '') {
                    var nodeId = data_nodes.filter(e => e.entityDeviceId === node.entityId)[0].id
                    dataLinks.push({
                        source: `${nodeId}`,
                        target: `${node.id}`
                    })
                }
            })
            // var width = 200 * mockBusLen
            // var height = 400
            return {
                dataNodes: dataNodes,
                dataLinks: dataLinks,
                // width: width,
                // height: height
            }
        }
        function createNetNodeDatas(data_nodes, o, radius) {
            function getNodePositon(n, r) {
                var angle = 2 * Math.PI / n
                var sumAngle = 0
                var arr = []
                for (var i = 0; i < n; i++) {
                    var x = r * Math.sin(sumAngle)
                    var y = r * Math.cos(sumAngle)
                    sumAngle += angle
                    var obj = {
                        x: x,
                        y: y
                    }
                    arr.push(obj)
                }
                return arr
            }
            var num = data_nodes.length
            var nodeLen = 0
            var dataNodes = []
            var dataLinks = []
            var mockBus = []
            var starR = radius
            // 制作data假节点
            var pointsArr = getNodePositon(num, starR)
            for (var i = 0; i < pointsArr.length; i++) {
                data_nodes[i].x = o.x + pointsArr[i].x
                data_nodes[i].y = o.y + pointsArr[i].y
                dataNodes.push(data_nodes[i])
                nodeLen++
            }
            // todo 网状,线条重复需要去重
            // 连接各data节点与中心节点
            dataNodes.forEach(element => {
                dataNodes.forEach(elements => {
                    if (element.id != elements.id)
                        dataLinks.push({
                            source: `${element.id}`,
                            target: `${elements.id}`
                        })
                })
            })

            // var width = 200 * mockBusLen
            // var height = 400
            return {
                dataNodes: dataNodes,
                dataLinks: dataLinks,
                width: starR,
                height: starR
            }
        }

        //基准圆点
        var o = { x: 0, y: 0 }
        var dataNodes
        var dataLinks

        // 总线图预览
        // var bus = createBusNodeDatas(data_busNodes, o)
        // console.log(bus);
        // dataNodes = bus.dataNodes
        // dataLinks = bus.dataLinks

        // 星型图预览
        // o = { x: 1000, y: 1000 }
        // var star = createStarNodeDatas(data_busNodes, o,200)
        // dataNodes = star.dataNodes
        // dataLinks = star.dataLinks

        // 环型图预览
        // o = { x: 2000, y: 2000 }
        // var star = createRingNodeDatas(data_busNodes, o,200)
        // dataNodes = star.dataNodes
        // dataLinks = star.dataLinks

        // 树型图预览
        o = { x: 0, y: 0 }
        var tree = createTreeNodeDatas(params, o, 200)
        console.log(tree);
        dataNodes = tree.dataNodes
        dataLinks = tree.dataLinks

        // 网状图预览
        // o = { x: 0, y: 0 }
        // var net = createNetNodeDatas(params, o, 200)
        // dataNodes = net.dataNodes
        // dataLinks = net.dataLinks

        // dataNodes = bus.dataNodes.concat(star.dataNodes)
        // dataLinks = bus.dataLinks.concat(star.dataLinks)

        // 创建chart 相当于new一个对象
        var chart = echarts.init(document.querySelector("div"));
        // 图表内容,样式
        var option = {
            title: {
                text: '拓扑图',
            },
            tooltip: {},
            // animationDurationUpdate: 10,
            // animationEasingUpdate: 'quinticInOut',
            // animationEasing: 'elasticOut',
            // animationDelayUpdate: function (idx) {
            //     return idx * 1;
            // },
            // grid: {
            //     show: false,
            //     y: '0',
            //     y2: '0',
            //     x: '0',
            //     x2: '0'
            // },
            series: [
                {
                    type: 'graph',
                    // layout: 'force',
                    symbolSize: 30,
                    // roam: true,
                    focusNodeAdjacency: true,
                    legend: {
                        left: 'left',
                        data: ['h1', 'h2', 'h3']
                    },
                    edgeSymbol: ['circle'],
                    edgeSymbolSize: [1, 1],
                    edgeLabel: {
                        normal: {
                            show: false
                        },
                        emphasis: {
                            textStyle: {
                                fontSize: 16
                            }
                        }
                    },
                    // animationDelay: function (idx) {
                    //     return idx * 300;
                    // },
                    force: {
                        edgeLength: 100,
                        // repulsion: 200,
                        gravity: 0,
                        // repulsion: 100
                    },
                    //节点信息
                    data: dataNodes,
                    links: dataLinks,
                    lineStyle: {
                        curveness: 0
                    },
                    zoom: 0.8
                }
            ],
        };
        option.series[0].data = option.series[0].data;
        option.series[0].links = option.series[0].links;
        //配置图表的样式
        chart.setOption(option);

        var doNode
        // 添加echarts 事件,'click'、'dblclick'、'mousedown'、'mousemove'、'mouseup'、'mouseover'、'mouseout'、'globalout'、'contextmenu'
        chart.on('mousedown', function (params) {
            console.warn(params, 'mousedown');
            doNode = params.data
            // console.warn(params.data.entityDeviceId);
        });

        chart.on('mousemove', function (params) {
            // console.log(params.event.offsetX, params.event.offsetY, 'moving');
            // var offsetX = params.event.offsetX
            // var offsetX = params.event.offsetY
            // console.log(offsetX, offsetY);
            // console.log(dataNodes.filter(i => i.entityDeviceId === doNode.entityDeviceId));
            // dataLinks
        });

        chart.on('click', function (params) {
            console.log(params, 'click');
        });

        chart.on('mouseup', function (params) {
            console.log(params, 'mouseup');
        });

        chart.on('globalout', function (params) {
            // 离开图层
            console.log(params, 'globalout');
        });

        var move = {
            offsetX: 0,
            offsetY: 0
        }
        var isClick = 0
        var canvas = document.querySelector('canvas')
        canvas.addEventListener('mousedown', function (e) {
            // console.log('mousedown', e);
            move.offsetX = e.offsetX
            move.offsetY = e.offsetY
            isClick = 1
        }, false)
        canvas.addEventListener('mouseup', function (e) {
            console.log('mouseup', e);
            move.offsetX = 0
            move.offsetY = 0
            isClick = 0
        })
        canvas.addEventListener('mousemove', debounce(function (e) {
            // console.log(e.offsetX, move.offsetX);
            if (isClick) {
                var offsetX = e.offsetX - move.offsetX
                var offsetY = e.offsetY - move.offsetY
                console.log('xChange: ' + offsetX, 'yChange: ' + offsetY);
            }
        }, 12, true))

        /**
         * 防反跳。fn函数在最后一次调用时刻的delay毫秒之后执行!
         * @param fn 执行函数
         * @param delay 时间间隔
         * @param isImmediate 为true,debounce会在delay时间间隔的开始时立即调用这个函数
         * @returns {Function}
         */
        function debounce(fn, delay, isImmediate) {
            var timer = null;  //初始化timer,作为计时清除依据
            return function () {
                var context = this;  //获取函数所在作用域this
                var args = arguments;  //取得传入参数
                clearTimeout(timer);
                if (isImmediate && timer === null) {
                    //时间间隔外立即执行
                    fn.apply(context, args);
                    timer = 0;
                    return;
                }
                timer = setTimeout(function () {
                    fn.apply(context, args);
                    timer = null;
                }, delay);
            }
        }
    </script>
</body>

</html>

标签:dataLinks,拓扑图,bus,dataNodes,echarts,星型,var,data,id
来源: https://www.cnblogs.com/lambertlt/p/16382407.html