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

如何实现Fl_charts中多折线图的Tooltip同步显示?

实现Fl_charts多折线图联动Tooltip方案

核心思路是通过共享状态管理当前悬停的数据点索引,让所有图表根据这个索引同步显示对应位置的Tooltip。具体实现步骤如下:

1. 定义共享状态

在StatefulWidget的状态类中,声明变量保存当前悬停的索引:

int? _hoveredIndex;

2. 配置图表触摸回调

为每个LineChart的lineTouchData添加自定义触摸逻辑,用于更新共享索引:

LineTouchData(
  touchCallback: (FlTouchEvent event, LineTouchResponse? response) {
    if (event is PointerHoverEvent) {
      // 获取当前悬停点的X轴索引
      final touchedSpot = response?.lineBarSpots?.first;
      if (touchedSpot != null) {
        setState(() {
          _hoveredIndex = touchedSpot.spotIndex;
        });
      }
    } else if (event is PointerExitEvent) {
      // 鼠标离开时重置索引
      setState(() {
        _hoveredIndex = null;
      });
    }
  },
  // 关闭默认Tooltip触发逻辑,改为手动控制
  enabled: false,
  // 自定义Tooltip显示规则
  getTooltipItems: (List<LineBarSpot> spots) {
    // 仅当共享索引匹配时返回Tooltip内容
    if (spots.isNotEmpty && spots.first.spotIndex == _hoveredIndex) {
      return [
        LineTooltipItem(
          '数值: ${spots.first.y.toStringAsFixed(2)}',
          const TextStyle(color: Colors.white),
        )
      ];
    }
    return [];
  },
)

3. 同步所有图表Tooltip

所有折线图都使用上述LineTouchData配置,这样任意一个图表触发索引更新时,其余图表会自动根据共享索引显示对应位置的Tooltip。

完整示例代码片段

class LinkedTooltipCharts extends StatefulWidget {
  const LinkedTooltipCharts({super.key});

  @override
  State<LinkedTooltipCharts> createState() => _LinkedTooltipChartsState();
}

class _LinkedTooltipChartsState extends State<LinkedTooltipCharts> {
  int? _hoveredIndex;

  // 模拟4组长度一致的测试数据
  final List<List<FlSpot>> _chartData = [
    List.generate(10, (i) => FlSpot(i.toDouble(), (i * 2).toDouble())),
    List.generate(10, (i) => FlSpot(i.toDouble(), (i * 3).toDouble())),
    List.generate(10, (i) => FlSpot(i.toDouble(), (i * 1.5).toDouble())),
    List.generate(10, (i) => FlSpot(i.toDouble(), (i * 2.5).toDouble())),
  ];

  Widget _buildChart(List<FlSpot> data) {
    return LineChart(
      LineChartData(
        lineTouchData: LineTouchData(
          touchCallback: (FlTouchEvent event, LineTouchResponse? response) {
            if (event is PointerHoverEvent) {
              final touchedSpot = response?.lineBarSpots?.first;
              if (touchedSpot != null) {
                setState(() {
                  _hoveredIndex = touchedSpot.spotIndex;
                });
              }
            } else if (event is PointerExitEvent) {
              setState(() {
                _hoveredIndex = null;
              });
            }
          },
          enabled: false,
          getTooltipItems: (List<LineBarSpot> spots) {
            if (spots.isNotEmpty && spots.first.spotIndex == _hoveredIndex) {
              return [
                LineTooltipItem(
                  '${spots.first.y.toStringAsFixed(2)}',
                  const TextStyle(color: Colors.white, fontSize: 12),
                )
              ];
            }
            return [];
          },
        ),
        gridData: const FlGridData(show: true),
        titlesData: const FlTitlesData(show: true),
        borderData: FlBorderData(show: true),
        lineBarsData: [
          LineChartBarData(
            spots: data,
            isCurved: true,
            color: Colors.blue,
            dotData: const FlDotData(show: true),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return GridView.count(
      crossAxisCount: 2,
      children: _chartData.map((data) => _buildChart(data)).toList(),
    );
  }
}

关键注意事项

  • 必须保证所有图表的X轴数据索引完全对应,否则会出现Tooltip错位
  • 若单图表包含多个数据系列,需在getTooltipItems中遍历所有系列的对应索引点,生成多个Tooltip条目
  • 可根据需求调整PointerExitEvent的处理逻辑,比如添加延迟重置,避免鼠标在图表间移动时Tooltip频繁消失

内容的提问来源于stack exchange,提问作者Mauro Gentile

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:13:27