ECharts多系列与单系列图表联动时echarts.connect失效问题问询
ECharts Connect 联动失效问题:隐藏多系列图表首个图例项后联动断开
问题描述
我在使用ECharts的联动功能时遇到了一个奇怪的问题,具体场景如下:
- 我创建了一个包含3个系列(A、B、C)的多系列图表(graph1)
- 同时创建了一个仅包含系列C的单系列图表(graph2),以及另一个包含2个系列(E、F)的多系列图表(graph3)
- 用
echarts.connect([chart1, chart2, chart3])将三个图表关联,原本期望tooltip和图例切换都能同步联动 - 但当我隐藏graph1里的第一个图例项(A)后,所有图表之间的联动关系直接断开了——tooltip不再同步,后续的图例切换也完全不会影响其他图表。
以下是复现问题的完整代码:
HTML代码
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.2.1/echarts.min.js"></script> <div> <div class="graph graph1" id="graph1" style="width: 500px; height: 300px;"></div> <div class="graph graph2" id="graph2" style="width: 500px; height: 300px;"></div> <div class="graph graph3" id="graph3" style="width: 500px; height: 300px;"></div> </div>
JavaScript代码
/** * example showing the issue with connect and legend */ let initGraphs = () => { let x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let y1 = [], y2 = [], y3 = [], y4 = [], y5 = [], y6 = []; let max = 2; let min = -2; for (i = 0; i <= 10; i++) { y1.push(Math.random() * (+max - +min) + +min) y2.push(Math.random() * (+max - +min) + +min) y3.push(Math.random() * (+max - +min) + +min) y4.push(Math.random() * (+max - +min) + +min) y5.push(Math.random() * (+max - +min) + +min) y6.push(Math.random() * (+max - +min) + +min) } let options = { legend: { data: ["A", "B", "C"], top: '17%', }, xAxis: { type: 'value', data: x }, yAxis: { type: 'value' }, series: [{ name: "A", data: y1, type: 'line', smooth: true }, { name: "B", data: y2, type: 'line', smooth: true }, { name: "C", data: y3, type: 'line', smooth: true }, ], tooltip: { trigger: "axis", showDelay: 0, } } let options2 = { xAxis: { type: 'value', data: x }, yAxis: { type: 'value' }, series: [{ name: "C", data: y3, type: 'line', smooth: true }], tooltip: { trigger: "axis", showDelay: 0, } } let options3 = { legend: { data: ["E", "F"], top: '17%', }, xAxis: { type: 'value', data: x }, yAxis: { type: 'value' }, series: [{ name: "E", data: y5, type: 'line', smooth: true }, { name: "F", data: y6, type: 'line', smooth: true } ], tooltip: { trigger: "axis", showDelay: 0, } } let chart1 = echarts.init(document.getElementById("graph1")); chart1.setOption(options); let chart2 = echarts.init(document.getElementById("graph2")); chart2.setOption(options2); let chart3 = echarts.init(document.getElementById("graph3")); chart3.setOption(options3); echarts.connect([chart1, chart2, chart3]) } initGraphs();
问题原因分析
这个问题是ECharts 4.2.1版本connect机制的一个缺陷:当你切换关联图表中仅存在于当前图表的系列的显示状态时,ECharts的自动联动逻辑会出现异常,导致整个联动组的同步机制彻底失效。
在你的场景里,graph1的系列A只在graph1中存在,当你隐藏A时,ECharts尝试同步这个系列的状态到其他关联图表,但找不到对应的系列,触发了内部的状态错误,进而导致整个联动组的所有同步(包括tooltip和后续图例切换)都停止工作。
解决方案
我们可以绕过ECharts自动联动的缺陷,通过手动监听图例事件并控制其他图表的系列状态来实现稳定的联动,同时保留tooltip的自动联动功能。
修改后的代码
let initGraphs = () => { let x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let y1 = [], y2 = [], y3 = [], y4 = [], y5 = [], y6 = []; let max = 2; let min = -2; for (i = 0; i <= 10; i++) { y1.push(Math.random() * (+max - +min) + +min) y2.push(Math.random() * (+max - +min) + +min) y3.push(Math.random() * (+max - +min) + +min) y4.push(Math.random() * (+max - +min) + +min) y5.push(Math.random() * (+max - +min) + +min) y6.push(Math.random() * (+max - +min) + +min) } let options = { legend: { data: ["A", "B", "C"], top: '17%', selected: { "A": true, "B": true, "C": true } // 明确初始化选中状态 }, xAxis: { type: 'value', data: x }, yAxis: { type: 'value' }, series: [{ name: "A", data: y1, type: 'line', smooth: true }, { name: "B", data: y2, type: 'line', smooth: true }, { name: "C", data: y3, type: 'line', smooth: true }, ], tooltip: { trigger: "axis", showDelay: 0, } } let options2 = { xAxis: { type: 'value', data: x }, yAxis: { type: 'value' }, series: [{ name: "C", data: y3, type: 'line', smooth: true, show: true // 初始化显示状态 }], tooltip: { trigger: "axis", showDelay: 0, } } let options3 = { legend: { data: ["E", "F"], top: '17%', selected: { "E": true, "F": true } }, xAxis: { type: 'value', data: x }, yAxis: { type: 'value' }, series: [{ name: "E", data: y5, type: 'line', smooth: true }, { name: "F", data: y6, type: 'line', smooth: true } ], tooltip: { trigger: "axis", showDelay: 0, } } let chart1 = echarts.init(document.getElementById("graph1")); chart1.setOption(options); let chart2 = echarts.init(document.getElementById("graph2")); chart2.setOption(options2); let chart3 = echarts.init(document.getElementById("graph3")); chart3.setOption(options3); // 仅开启tooltip的自动联动,避免图例自动联动触发bug echarts.connect([chart1, chart2, chart3], 'tooltip'); // 手动监听graph1的图例切换事件 chart1.on('legendselectchanged', function (params) { const seriesName = params.name; const isSelected = params.selected[seriesName]; // 只对跨图表共享的系列(C)进行状态同步 if (seriesName === 'C') { chart2.dispatchAction({ type: 'legendToggleSelect', name: seriesName }); } // 仅存在于当前图表的系列(A、B),只处理自身状态即可 }); // 监听graph3的图例切换事件,按需处理(这里保持默认,只影响自身) chart3.on('legendselectchanged', function (params) { // 若需要跨图表联动E/F系列,可在此添加对应逻辑 }); } initGraphs();
关键改动说明
- 限制联动范围:用
echarts.connect([chart1, chart2, chart3], 'tooltip')只让tooltip保持自动联动,避开图例自动联动的bug。 - 手动控制图例联动:监听
legendselectchanged事件,仅对跨图表共享的系列(比如C)进行状态同步,对于仅存在于单个图表的系列,只处理当前图表的状态,不触发全局联动。 - 明确初始化状态:显式设置
legend.selected和series.show,确保所有图表初始状态一致,避免潜在的状态冲突。
这种方式可以完全避免原版本中因非共享系列图例切换导致的联动失效问题,同时保留了需要的联动功能。
内容的提问来源于stack exchange,提问作者tzim




