You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Apache ECharts图例点击行为为单选显示模式?

实现ECharts图例单选切换功能

需求说明

使用ReactECharts绘制折线图时,默认点击图例是隐藏对应系列,需要改为:

  • 点击图例项时,仅显示该系列,隐藏其他所有系列
  • 再次点击已选中的图例项,取消单选,恢复显示所有系列

实现步骤

  1. 添加状态管理:用useState维护当前单选的系列名称,初始值为null表示未进入单选模式
  2. 监听图例点击事件:通过ReactECharts的onEvents属性监听legendselectchanged事件
  3. 编写事件处理逻辑:根据当前选中状态切换系列的显示/隐藏
  4. 动态控制系列可见性:在生成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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 23:01:03