如何修改Apache ECharts图例点击行为为单选显示模式?
实现ECharts图例单选切换功能
需求说明
使用ReactECharts绘制折线图时,默认点击图例是隐藏对应系列,需要改为:
- 点击图例项时,仅显示该系列,隐藏其他所有系列
- 再次点击已选中的图例项,取消单选,恢复显示所有系列
实现步骤
- 添加状态管理:用
useState维护当前单选的系列名称,初始值为null表示未进入单选模式 - 监听图例点击事件:通过ReactECharts的
onEvents属性监听legendselectchanged事件 - 编写事件处理逻辑:根据当前选中状态切换系列的显示/隐藏
- 动态控制系列可见性:在生成series时根据状态设置
visible属性
修改后的完整代码
import { useState, useRef } from 'react'; import ReactECharts from 'echarts-for-react'; import * as echarts from 'echarts'; // 假设dataMap、colors、now、selectedTime、paperSize、yAxisNameGap已定义 const YourChartComponent = () => { const chartRef = useRef<ReactECharts>(null); const [activeSingleSeries, setActiveSingleSeries] = useState<string | null>(null); const getChartSeries = () => { return Object.entries(dataMap).map(([key, values], index) => { // 根据activeSingleSeries判断当前系列是否可见 const isVisible = activeSingleSeries === null || activeSingleSeries === key; return { name: key, type: 'line', smooth: true, showSymbol: false, visible: isVisible, data: values.map(({ timestamp, value }) => [timestamp, value]), lineStyle: { normal: { color: colors[index % colors.length], } }, itemStyle: { color: colors[index % colors.length] } }; }); }; // 图例点击事件处理 const handleLegendSelect = (params: echarts.EChartsEvent) => { const { name, selected } = params as any; const isSelected = selected[name]; if (activeSingleSeries === null) { // 未进入单选模式,点击后进入单选,只显示当前系列 if (isSelected) { setActiveSingleSeries(name); } } else { if (name === activeSingleSeries) { // 点击已选中的系列,取消单选,恢复所有显示 setActiveSingleSeries(null); } else { // 单选模式下切换到新系列 setActiveSingleSeries(name); } } }; const chartWithData = ( <ReactECharts ref={chartRef} option={{ tooltip: { trigger: 'axis', formatter: function (params: any[]) { const formattedSeriesName = (name: string) => { return name.replace('_', ' ').replace(/\b\w/g, char => char.toUpperCase()); }; const time = params[0].axisValueLabel; let content = '<div style="line-height: 1.5; text-align: left;">' + time + '</div>'; let names = ''; let values = ''; params.forEach(function (item: any) { const formattedName = formattedSeriesName(item.seriesName); names += '<div style="line-height: 1.5; text-align: left; ">' + item.marker + ' ' + formattedName + '</div>'; let value: string; if (Number.isInteger(item.value[1])) { value = item.value[1].toString(); } else { value = item.value[1].toFixed(2); } values += '<div style="line-height: 1.5; text-align: right; font-weight: bold;">' + value + '</div>'; }); content += '<div style="display: inline-block; vertical-align: top; margin-right: 10px;">' + names + '</div>' + '<div style="display: inline-block; vertical-align: top;">' + values + '</div>'; return content; } }, legend: { data: Object.keys(dataMap), bottom: 1, show: true, type: 'scroll', icon: 'circle', formatter: function (name: string) { const formattedName = name.replace('_', ' ').replace(/\b\w/g, char => char.toUpperCase()); return formattedName; }, }, grid: { left: '13%', right: '5%', top: '10%', bottom: '15%' }, xAxis: { type: 'time', splitNumber: 5, min: now.getTime() - Number(selectedTime) * 1000, max: now, axisLabel: { formatter: function (value: Date) { return echarts.format.formatTime('hh:mm', value); } }, }, yAxis: { type: 'value', axisLine: { show: true, }, name: 'Transaction / minute', nameLocation: "middle", nameGap: yAxisNameGap, }, series: getChartSeries(), }} onEvents={{ legendselectchanged: handleLegendSelect }} style={{ height: paperSize.height - 40, padding: 5 }} /> ); return chartWithData; }; export default YourChartComponent;
关键说明
- 用
activeSingleSeries状态变量标记当前是否处于单选模式,以及选中的系列名称 - 生成series时,通过
visible属性控制每个系列的显示状态 - 监听
legendselectchanged事件,根据当前状态切换单选/全显模式 - 修正了原代码中
colorIndex的闭包问题,改用map的索引来获取颜色,避免状态异常
内容的提问来源于stack exchange,提问作者DMT PYTN
相关产品推荐
相关产品推荐

