第22章:ECharts 图表联动(多图表交互联动)
功能说明:页面放置2 个独立图表 ,点击第一个图表的数据项,第二个图表自动刷新对应明细数据;同时复用我们已经封装好的
useEcharts,自带防抖 resize、实例就绪等待、导出功能。
页面完整代码
<template>
<div class="chart-link-page">
<el-card style="margin-bottom:20px">
<template #header>
<div>图表联动演示|点击上方柱状图,下方饼图自动切换明细</div>
</template>
<el-row :gutter="20">
<el-col :span="12">
<div ref="chartRef1" style="width:100%;height:350px;border:1px solid #eee"></div>
</el-col>
<el-col :span="12">
<div ref="chartRef2" style="width:100%;height:350px;border:1px solid #eee"></div>
</el-col>
</el-row>
</el-card>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useEcharts } from '@/composables/echartHelper'
// 实例化两个独立图表,每个图表单独调用useEcharts
const {
chartRef: chartRef1,
setChartOption: setOption1,
onChartEvent: onEvent1
} = useEcharts()
const {
chartRef: chartRef2,
setChartOption: setOption2
} = useEcharts()
// 模拟总数据
const totalData = [
{ name: '1月', value: 120, detail: [{ name: 'A产品', val: 70 }, { name: 'B产品', val: 50 }] },
{ name: '2月', value: 200, detail: [{ name: 'A产品', val: 110 }, { name: 'B产品', val: 90 }] },
{ name: '3月', value: 150, detail: [{ name: 'A产品', val: 80 }, { name: 'B产品', val: 70 }] },
{ name: '4月', value: 280, detail: [{ name: 'A产品', val: 160 }, { name: 'B产品', val: 120 }] },
]
// 左侧柱状图配置
const barOption = {
title: { text: '月度总销售额', left: 'center' },
tooltip: { trigger: 'axis' },
xAxis: {
type: 'category',
data: totalData.map(item => item.name)
},
yAxis: { type: 'value', name: '万元' },
series: [
{
name: '销售额',
type: 'bar',
data: totalData.map(item => item.value),
itemStyle: { color: '#409EFF' }
}
]
}
// 初始化饼图(默认显示1月数据)
function initPie(dataItem) {
const pieOption = {
title: { text: `${dataItem.name}产品明细`, left: 'center' },
tooltip: { trigger: 'item' },
series: [
{
type: 'pie',
radius: ['40%', '70%'],
data: dataItem.detail.map(d => ({ name: d.name, value: d.val }))
}
]
}
setOption2(pieOption)
}
onMounted(async () => {
// 渲染柱状图
await setOption1(barOption)
// 默认加载第一个月饼图
initPie(totalData[0])
})
// 核心联动逻辑:点击柱状图,更新饼图
onEvent1('click', (params) => {
const clickItem = totalData.find(item => item.name === params.name)
if (clickItem) {
initPie(clickItem)
}
})
</script>
核心知识点
- 多个图表就要多次调用
useEcharts(),每个图表拥有独立实例、独立 ref,互不干扰; - 利用
onChartEvent监听点击事件,拿到点击的参数,筛选对应明细数据; - 调用
setChartOption更新第二个图表,内部自带notMerge:true,会完全覆盖旧图表配置,不会出现残留文字; - 自带窗口 resize 防抖,两个图表都会自动自适应。
🧪 测试清单
- 保存页面,刷新浏览器;
- 页面左右两个图表正常渲染,右侧饼图默认展示 1 月明细;
- 点击左侧柱状图的【2 月】柱子,右侧饼图自动切换为 2 月 A/B 产品数据;
- 切换浏览器窗口大小,两张图表同时自适应缩放;
- 切换菜单离开页面,图表实例自动销毁,无内存泄漏。
