ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-06-16 16:35:10  阅读:195  来源: 互联网

标签:dataLinks 拓扑图 bus dataNodes echarts 星型 var data id


树形

网状

环形

星形

总线形

<!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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有