Vue - 使用 Echarts 实现显示拓扑图效果
·
1. 安装Echarts
npm install echarts@5.3.2 --save
2. 页面代码
<!-- 拓扑图组件的模板结构 -->
<template>
<div class="topology-container">
<div ref="chart" class="chart-box"></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'TopologyChart',
data() {
return {
chartInstance: null,
resizeChart: null,
topologyData: {
nodes: [],
links: [],
categories: []
}
}
},
mounted() {
// 该方法用来获取数据
this.getData()
},
beforeDestroy() {
if (this.chartInstance) this.chartInstance.dispose()
window.removeEventListener('resize', this.resizeChart)
},
methods: {
getData() {
// 获取数据
const resData = [
{ id: 1, name: '节点1', value: 100 },
{ id: 2, name: '节点2', value: 200 },
{ id: 3, name: '节点3', value: 300 },
{ id: 4, name: '节点4', value: 400 },
{ id: 5, name: '节点5', value: 500 },
{ id: 6, name: '节点6', value: 600 },
{ id: 7, name: '节点7', value: 700 },
{ id: 8, name: '节点8', value: 800 },
]
this.topologyData.nodes = resData
/**
* 静态数据
* key 为节点id,值为节点坐标和指向的节点id
* x 为节点x坐标左右偏移
* y 为节点y坐标上下偏移
* lineToNode 为指向的节点id,可以有多个
* */
const staticData = {
1: { x: 100, y: 100, lineToNode: [2, 3], symbol: 'image://' + require('@/assets/images/node1.png') },
2: { x: 200, y: 200, lineToNode: [1, 3], symbol: 'image://' + 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png' },
3: { x: 300, y: 300, lineToNode: [1, 2], symbol: 'image://' + require('@/assets/images/node3.png') },
4: { x: 400, y: 400, lineToNode: [1, 2, 3], symbol: 'image://' + require('@/assets/images/node4.png') },
5: { x: 500, y: 500, lineToNode: [1, 3, 4], symbol: 'image://' + require('@/assets/images/node5.png') },
6: { x: 600, y: 600, lineToNode: [1, 5], symbol: 'image://' + require('@/assets/images/node6.png') },
7: { x: 700, y: 700, lineToNode: [1, 4, 5], symbol: 'image://' + require('@/assets/images/node7.png') },
8: { x: 800, y: 800, lineToNode: [1, 6, 7], symbol: 'image://' + require('@/assets/images/node8.png') },
}
// 根据静态数据生成连线数据
this.topologyData.nodes = resData.map(item => {
return {
...item,
x: staticData[item.id]?.x || 0,
y: staticData[item.id]?.y || 0,
symbol: staticData[item.id]?.symbol || null,
symbolSize: staticData[item.id]?.symbolSize || 60,
lineToNode: staticData[item.id]?.lineToNode || []
}
})
// 处理连线数据
let links = []
for (const key in staticData) {
const item = staticData[key]
if(item.lineToNode && item.lineToNode.length) {
item.lineToNode.forEach(nodeId => {
links.push({
source: key + '',
target: nodeId + ''
})
})
}
}
this.topologyData.links = links
// 渲染ECharts
this.initChart()
},
initChart() {
this.chartInstance = echarts.init(this.$refs.chart)
this.resizeChart = () => this.chartInstance?.resize()
window.addEventListener('resize', this.resizeChart)
const option = {
tooltip: { trigger: 'item' },
legend: { show: false },
series: [
{
type: 'graph',
roam: true, // 是否允许拖拽
zoom: 1, // 缩放比例
// layout: 'force', // 力导布局
// force: {
// repulsion: 800, // 增大节点间斥力,让节点更分散
// edgeLength: 200, // 缩短连线长度,避免布局松散
// gravity: 0.1, // 轻微向中心聚拢,防止节点飘到边缘
// layoutAnimation: false // 关闭布局动画,直接渲染最终位置
// },
layout: 'none', // 不布局
force: {
repulsion: 0, // 排斥力
layoutAnimation: false // 关闭布局动画,直接渲染最终位置
},
symbol: null,
symbolSize: 60, // 缩小节点尺寸,给文字更多空间
label: {
show: true,
color: '#fff',
fontSize: 25, // 缩小字体,减少重叠概率
position: 'bottom',
distance: 8, // 缩短文字与图标的距离,避免文字扩散
overflow: 'truncate', // 超长文字自动截断,防止遮挡
ellipsis: '...' // 截断后显示省略号
},
edgeSymbol: ['none', 'arrow'], // 连线箭头类型
edgeSymbolSize: [0, 8], // 连线箭头大小
lineStyle: {
color: '#cccccc', // 连线颜色
width: 1 // 连线宽度
},
data: this.topologyData.nodes,
links: this.topologyData.links,
categories: this.topologyData.categories
}
]
}
this.chartInstance.setOption(option)
}
}
}
</script>
<style scoped>
.topology-container {
width: 100%;
height: 900px; /* 增加容器高度,给纵向更多布局空间 */
padding: 20px;
box-sizing: border-box;
}
.chart-box {
width: 100%;
height: 100%;
}
</style>
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)