ECharts是一款由百度开源的数据可视化图表库,它提供了丰富的图表类型以及高度可定制化的选项。结合Vue3的强大响应式能力和生态,我们可以轻松地创建出一个具有动态效果和良好用户体验的拓扑图。本文将通过一个具体的代码示例,详细介绍如何实现这一目标。
实现效果如图
环境准备
首先,确保你的开发环境中已经安装了Node.js。接下来,我们需要安装Vue CLI以及Vue3和ECharts。
安装Vue CLI
npm install -g @vue/cli
创建Vue3项目
vue create my-vue3-project
cd my-vue3-project
npm install
安装Vue3和ECharts
npm install vue@next echarts
创建Vue3组件
我们将创建一个新的Vue3单文件组件(SFC),用于展示拓扑图。
文件结构
my-vue3-project/
├── src/
│ ├── components/
│ │ └── TopologyChart.vue
│ └── App.vue
└── public/
└── index.html
TopologyChart.vue
组件
<template>
<div>
<div id="topology_chart" style="width: 100%; height: 400px;" />
</div>
</template>
<script setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue'
import * as echarts from 'echarts'
// 示例数据
const topologyDatas = ref([
{
name: 'Root Node 1',
level: 1,
symbol: 'image:///img/icon1.png', // 图标路径
symbolSize: 50,
datas: {
department: 'Department A',
description: 'Description of Root Node 1'
},
children: [
{
name: 'Child Node 1-1',
level: 2,
symbol: 'image:///img/icon2.png',
symbolSize: 40,
datas: {
department: 'Subdepartment A',
description: 'Description of Child Node 1-1'
},
children: [
{
name: 'Grandchild Node 1-1-1',
level: 3,
symbol: 'image:///img/icon3.png',
symbolSize: 30,
datas: {
department: 'Sub-subdepartment A',
description: 'Description of Grandchild Node 1-1-1'
}
},
{
name: 'Grandchild Node 1-1-2',
level: 3,
symbol: 'image:///img/icon4.png',
symbolSize: 30,
datas: {
department: 'Sub-subdepartment B',
description: 'Description of Grandchild Node 1-1-2'
}
}
]
},
{
name: 'Child Node 1-2',
level: 2,
symbol: 'image:///img/icon5.png',
symbolSize: 40,
datas: {
department: 'Subdepartment B',
description: 'Description of Child Node 1-2'
},
children: [
{
name: 'Grandchild Node 1-2-1',
level: 3,
symbol: 'image:///img/icon6.png',
symbolSize: 30,
datas: {
department: 'Sub-subdepartment C',
description: 'Description of Grandchild Node 1-2-1'
}
}
]
}
]
},
{
name: 'Root Node 2',
level: 1,
symbol: 'image:///img/icon7.png',
symbolSize: 50,
datas: {
department: 'Department B',
description: 'Description of Root Node 2'
},
children: [
{
name: 'Child Node 2-1',
level: 2,
symbol: 'image:///img/icon8.png',
symbolSize: 40,
datas: {
department: 'Subdepartment C',
description: 'Description of Child Node 2-1'
}
}
]
}
])
// 初始化图表
const initChart = () => {
const chartDom = document.getElementById('topology_chart');
const myChart = echarts.init(chartDom);
const option = {
dataZoom: [
{
type: 'slider',
show: true
}
],
series: [
{
type: 'tree',
initialTreeDepth: 2,
data: topologyDatas.value,
lineStyle: {
color: '#35EB68' // 设置线条颜色
},
top: 60,
left: 20,
right: 20,
bottom: 60,
orient: 'vertical',
edgeShape: 'polyline',
expandAndCollapse: true,
roam: true, // 启用平移和缩放
zoom: true, // 允许缩放
pan: true, // 允许平移
label: {
fontSize: 12,
position: 'right',
formatter: (params) => formatLabel(params),
rich: {
a: { lineHeight: 22, color: '#fff', fontSize: 12 },
b: { lineHeight: 22, color: '#fff', fontSize: 12 },
c: { lineHeight: 22, color: '#fff', fontSize: 12 }
}
},
leaves: {
label: {
position: 'right'
}
}
}
]
};
myChart.setOption(option);
myChart.resize();
window.addEventListener('resize', () => {
myChart.resize();
});
return myChart;
};
// 格式化标签
const formatLabel = (params) => {
let res = '';
if (params.data.level === 1) {
res += `{a|部门:${params.data.datas.department}}\n{b|描述:${params.data.datas.description}}`;
} else if (params.data.level === 2) {
res += `{c|部门:${params.data.datas.department}}\n{c|描述:${params.data.datas.description}}`;
} else {
res += `{c|部门:${params.data.datas.department}}\n{c|职责:${params.data.datas.description}}`;
}
return res;
};
// 组件挂载后初始化图表
let chartInstance;
onMounted(() => {
nextTick(() => {
chartInstance = initChart();
});
});
// 清除事件监听器,防止内存泄漏
onUnmounted(() => {
window.removeEventListener('resize', () => chartInstance?.resize());
chartInstance?.dispose();
});
</script>
<style scoped>
/* 可以在这里添加CSS样式 */
</style>
数据源结构
在上述代码中,topologyDatas
定义了一个包含多个根节点(root node)的数据结构。每个根节点可以有多个子节点(child node),子节点又可以有多个子节点,以此类推。每个节点包含以下属性:
- name:节点的名称。
- level:节点所在的层级。
- symbol:节点的图标路径。
- symbolSize:节点图标的大小。
- datas:附加的信息,如部门名称和描述。
- children:子节点列表。
例如:
{
name: 'Root Node 1',
level: 1,
symbol: 'image:///img/icon1.png',
symbolSize: 50,
datas: {
department: 'Department A',
description: 'Description of Root Node 1'
},
children: [
// 子节点
]
}
符号(Symbol)
在ECharts中,symbol
属性用于定义图表中数据点的符号形状。您可以使用各种预定义的形状,也可以使用图像作为符号。在本例中,我们使用图像作为符号:
symbol: 'image:///img/icon1.png',
这里的 'image:///img/icon1.png'
表示使用位于 /img/icon1.png
的图像作为节点的图标。
初始化图表
initChart
函数负责初始化ECharts图表,并设置基本的配置选项。其中包括:
- dataZoom:数据缩放组件,用于实现数据区域缩放功能。
- series.tree:树形图的配置项,包括初始展开的深度、方向、边的形状等。
- label.formatter:标签格式化函数,用于自定义节点上的标签内容。
生命周期管理
使用Vue3的组合API (onMounted
, onUnmounted
) 来控制图表的初始化和销毁过程,确保图表能够在组件挂载时初始化,并在组件卸载时清除事件监听器。
使用组件
在App.vue
中引入并使用TopologyChart.vue
组件。
<template>
<div id="app">
<TopologyChart />
</div>
</template>
<script>
import TopologyChart from './components/TopologyChart.vue';
export default {
name: 'App',
components: {
TopologyChart
}
}
</script>
<style>
/* 全局样式 */
</style>
总结
通过上述步骤,我们成功地使用Vue3和ECharts实现了一个带有图标节点的拓扑图。这种图不仅能够直观地展示数据之间的关系,还通过添加图标增强了视觉效果。你可以进一步扩展此示例,比如增加更多的交互功能或改变图表样式,以满足不同的需求。
希望这篇文章能帮助你更好地理解和使用Vue3和ECharts来创建拓扑图。如果有什么问题或建议,请随时留言交流!