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

如何在fl_chart折线图中使用DateTime/String作为坐标轴值?

解决fl_chart中X轴使用DateTime/String的问题

fl_chart的FlSpot确实只接受double类型作为坐标值,但我们可以通过数值映射+自定义轴标签的方式实现DateTime/String作为X轴显示,分两步走:

1. 把DateTime/String转成double类型存入FlSpot

针对DateTime的情况

将DateTime转换成时间戳(毫秒/秒)的double值,比如用millisecondsSinceEpoch:

spots: graphValues
    .map(
      (e) => FlSpot(
        (e['x'] as DateTime).millisecondsSinceEpoch.toDouble(), // DateTime转时间戳double
        (e['y'] as num).toDouble(),
      ),
    )
    .toList(),

针对String(类别型)的情况

给每个String分配连续的索引值(0、1、2...)作为double:

// 先提取所有X轴的String标签
final xLabels = graphValues.map((e) => e['x'] as String).toList();

spots: graphValues
    .map(
      (e) => FlSpot(
        xLabels.indexOf(e['x']).toDouble(), // String转索引double
        (e['y'] as num).toDouble(),
      ),
    )
    .toList(),

2. 自定义X轴标签,把double转回去显示DateTime/String

在LineChartData的titlesData中配置bottomTitles,自定义标签生成逻辑:

显示DateTime的完整示例

LineChart(
  LineChartData(
    titlesData: FlTitlesData(
      bottomTitles: AxisTitles(
        sideTitles: SideTitles(
          showTitles: true,
          reservedSize: 30, // 预留标签显示空间
          getTitlesWidget: (value, meta) {
            // 把时间戳double转回DateTime,再转成想要的格式
            final date = DateTime.fromMillisecondsSinceEpoch(value.toInt());
            return Text(
              "${date.month}/${date.day}", // 自定义日期格式,比如MM/DD
              style: const TextStyle(fontSize: 10),
            );
          },
        ),
      ),
      // 隐藏不需要的轴标签
      topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
      rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
    ),
    borderData: FlBorderData(show: false),
    lineBarsData: [
      LineChartBarData(
        spots: graphValues
            .map(
              (e) => FlSpot(
                (e['x'] as DateTime).millisecondsSinceEpoch.toDouble(),
                (e['y'] as num).toDouble(),
              ),
            )
            .toList(),
        isCurved: true,
        color: Colors.red,
        dotData: const FlDotData(show: false),
        barWidth: 1,
        belowBarData: BarAreaData(
          show: true,
          gradient: LinearGradient(
            colors: [
              const Color(0xFF222E65).withOpacity(.6),
              Colors.transparent
            ],
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
          ),
        ),
      ),
    ],
  ),
)

显示String类别的示例

final xLabels = graphValues.map((e) => e['x'] as String).toList();

LineChart(
  LineChartData(
    titlesData: FlTitlesData(
      bottomTitles: AxisTitles(
        sideTitles: SideTitles(
          showTitles: true,
          reservedSize: 30,
          getTitlesWidget: (value, meta) {
            // 通过索引获取对应的String标签
            final index = value.toInt();
            if (index >= 0 && index < xLabels.length) {
              return Text(
                xLabels[index],
                style: const TextStyle(fontSize: 10),
              );
            }
            return const Text('');
          },
        ),
      ),
      topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
      rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
    ),
    borderData: FlBorderData(show: false),
    lineBarsData: [
      LineChartBarData(
        spots: graphValues
            .map(
              (e) => FlSpot(
                xLabels.indexOf(e['x']).toDouble(),
                (e['y'] as num).toDouble(),
              ),
            )
            .toList(),
        isCurved: true,
        color: Colors.red,
        dotData: const FlDotData(show: false),
        barWidth: 1,
        belowBarData: BarAreaData(
          show: true,
          gradient: LinearGradient(
            colors: [
              const Color(0xFF222E65).withOpacity(.6),
              Colors.transparent
            ],
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
          ),
        ),
      ),
    ],
  ),
)

注意点

  • 如果DateTime的时间跨度很大,可通过minX/maxX设置轴的区间,避免标签过于密集
  • 对于String类别,需确保每个类别对应的索引唯一,避免重复映射

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 08:24:56