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

如何在Flutter应用中为Firebase数据添加样条图可视化?

实现Flutter样条图(基于Firebase数据)

步骤1:添加依赖

在项目的pubspec.yaml中引入所需依赖:

dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^2.15.0
  cloud_firestore: ^4.9.0
  syncfusion_flutter_charts: ^22.2.10
  intl: ^0.18.1 # 用于日期解析与格式化

执行flutter pub get完成依赖安装。

步骤2:初始化Firebase

在main.dart中完成Firebase初始化:

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart'; // Firebase CLI生成的配置文件

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(const MyApp());
}

步骤3:定义数据模型

创建与Firebase数据对应的Dart类,并实现从Firestore文档转换的方法:

import 'package:intl/intl.dart';

class Expense {
  final double amount;
  final String category;
  final DateTime date;

  Expense({
    required this.amount,
    required this.category,
    required this.date,
  });

  // 从Firestore文档转成Expense对象
  factory Expense.fromFirestore(Map<String, dynamic> data) {
    final dateStr = data['date'];
    final date = DateFormat('dd-MMM-yyyy hh:mm a').parse(dateStr);
    return Expense(
      amount: data['amount'].toDouble(),
      category: data['category'],
      date: date,
    );
  }
}

步骤4:从Firebase读取数据

实现获取Firestore数据的异步方法:

import 'package:cloud_firestore/cloud_firestore.dart';

Future<List<Expense>> getExpenses() async {
  // 替换为你实际的Firestore集合名称
  final snapshot = await FirebaseFirestore.instance.collection('expenses').get();
  return snapshot.docs.map((doc) => Expense.fromFirestore(doc.data())).toList();
}

步骤5:处理数据适配样条图

将原始数据按日期分组聚合(按日统计总金额),并排序:

Map<DateTime, double> groupExpensesByDay(List<Expense> expenses) {
  final grouped = <DateTime, double>{};
  for (var expense in expenses) {
    // 仅保留日期部分,忽略时间
    final dateKey = DateTime(expense.date.year, expense.date.month, expense.date.day);
    grouped[dateKey] = (grouped[dateKey] ?? 0) + expense.amount;
  }
  // 按日期排序
  final sortedEntries = grouped.entries.toList()
    ..sort((a, b) => a.key.compareTo(b.key));
  return Map.fromEntries(sortedEntries);
}

步骤6:构建样条图组件

用FutureBuilder处理异步数据加载,渲染样条图:

import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:intl/intl.dart';

class SplineChartScreen extends StatelessWidget {
  const SplineChartScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('支出趋势样条图')),
      body: FutureBuilder<List<Expense>>(
        future: getExpenses(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          }
          if (snapshot.hasError) {
            return Center(child: Text('加载失败: ${snapshot.error}'));
          }
          final expenses = snapshot.data!;
          final groupedData = groupExpensesByDay(expenses);
          // 转换为图表所需的数据源格式
          final chartData = groupedData.entries.map((entry) => ChartData(entry.key, entry.value)).toList();

          return SfCartesianChart(
            title: const ChartTitle(text: '每日支出趋势'),
            primaryXAxis: DateTimeAxis(
              title: const AxisTitle(text: '日期'),
              dateFormat: DateFormat('dd-MMM'),
            ),
            primaryYAxis: NumericAxis(
              title: const AxisTitle(text: '金额'),
              numberFormat: NumberFormat.currency(symbol: '\$'), // 可替换为目标货币符号
            ),
            series: <ChartSeries>[
              SplineSeries<ChartData, DateTime>(
                dataSource: chartData,
                xValueMapper: (ChartData data, _) => data.date,
                yValueMapper: (ChartData data, _) => data.amount,
                markerSettings: const MarkerSettings(isVisible: true), // 显示数据点标记
                name: '支出',
              ),
            ],
            tooltipBehavior: TooltipBehavior(enable: true), // 开启数据提示框
          );
        },
      ),
    );
  }
}

// 图表专用数据模型
class ChartData {
  final DateTime date;
  final double amount;

  ChartData(this.date, this.amount);
}

额外说明

  • 确保Firebase平台配置文件已正确添加(Android端的google-services.json、iOS端的GoogleService-Info.plist)。
  • 如需按类别区分多条样条线,可修改数据处理逻辑,按category分组后添加多个SplineSeries。
  • 日期解析格式需与Firebase中存储的字符串完全匹配,若格式不同需调整DateFormat的参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 06:45:30