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