如何用charts_flutter创建Flutter图表

3,817 阅读10分钟

应用程序中的图表提供了数据的图形显示或图画表示,跨越了行业和应用程序。像Mint这样的移动应用程序使用饼状图来监测消费习惯,像Strava这样的健身应用程序使用线状图和条状图来分析步幅、心率和海拔高度。

在构建Flutter应用程序时,开发者可以使用由谷歌维护的官方charts_flutter 库来创建这些类型的图表。

在本教程中,我们将学习如何使用charts_flutter 创建一些最常见的图表--线形图、饼图和条形图。

我们将用这些图表来显示一个虚构的Flutter图表开发者社区五年来的增长情况。虽然本教程中的数据是捏造的,但本教程可以很容易地利用真实数据。

前提条件

要学习本教程,您必须具备以下条件。

创建并设置一个Flutter项目charts_flutter

要创建一个新的Flutter项目,运行以下命令。

flutter create projectName

接下来,在您的代码编辑器中打开这个新项目。如上所述,我们将使用[chart_flutter](https://pub.dev/packages/charts_flutter) ,Flutter的官方库

要将chart_flutter 导入您的项目,请打开pubspec.yaml 文件并将其添加到依赖项下。

dependencies:
  flutter:
    sdk: flutter

  charts_flutter: ^0.11.0

构建应用程序的脚手架

现在我们有了新的Flutter应用程序所附带的基本代码:一个记录按钮被按下多少次的计数器。

由于我们的条形图应用程序中不需要这个,继续删除在main.dart 页面中发现的代码。删除所有的内容,除了下面的内容。

importpackage:flutter/material.dart’;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
            //TODO: implement build
            Return MaterialApp(
            );
     }
}

现在,在我们的构建部件中返回MaterialApp 类,以便我们可以使用Material Design。

创建一个主页

要为我们的应用程序创建一个主页,请导航到lib 文件夹,并创建一个名为home.dart 的新页面。

import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ,
      ),
    );
  }
}

通过import 'package:flutter/material.dart' ,我们就可以导入Material Design。

然后,HomePage 类扩展了statelessWidget ,因为在这个页面上没有状态变化。

BuildContext widget里面,我们返回Scaffold 类,给我们一个基本的Material Design布局结构。我们的条形图将放在子参数的位置,我们将把它放在屏幕主体的中心。

所有这些现在都成为我们应用程序的支架。

随着主页的完成,我们可以在我们的main.dart 文件中指定HomePage ,因为main.dart 将我们应用程序中的所有功能集中在一起。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(), //This is where we specify our homepage
    );
  }
}

有了这段代码,main.dart 就知道每当应用加载时首先显示哪一页。

请注意,将debugShowCheckedModeBanner 设置为false ,就可以从我们的应用程序中删除调试标记。

创建一个Flutter图表应用程序

系列和模型

在我们创建图表应用之前,让我们熟悉一下Flutter图表常用的两个术语:系列和模型。

系列是一组(或系列)的信息,我们可以用它来绘制我们的图表。一个模型是我们的信息的格式,它规定了使用该模型的每个数据项必须具有的属性。

创建一个条形图

为柱状图数据创建一个模型

首先,我们将创建一个柱状图,以显示在过去五年中新增的虚构Flutter图表开发者的数量。换句话说,我们要跟踪虚构的Flutter图表社区的增长情况。

我们的模型,定义了我们的数据格式,包括我们要看的年份,那一年加入Flutter图表社区的开发者数量,以及相应条形图的颜色。

lib 文件夹中,创建一个名为developer_series.dart 的文件。下面,实现我们模型的代码。

import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/foundation.dart';

class DeveloperSeries {
  final int year;
  final int developers;
  final charts.Color barColor;

  DeveloperSeries(
    {
      @required this.year,
      @required this.developers,
      @required this.barColor
    }
  );
}

我们将模型命名为DeveloperSeries ,并指定了每个系列项目必须具备的属性(year,developers, 和barColor )。

为了防止在创建一个类的对象时,该类的参数为空,我们使用了@required 注释,如上面的代码块中所示。

要使用@required 关键字,我们必须导入foundation.dart 包。

为柱状图创建数据

现在我们有了一个条形图数据的模型,让我们继续实际创建一些数据。在主页上,通过添加以下内容为柱状图生成数据。

 import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:;lib/developer_series.dart';

class HomePage extends StatelessWidget {
  final List<DeveloperSeries> data = [

    DeveloperSeries(
      year: "2017",
      developers: 40000,
      barColor: charts.ColorUtil.fromDartColor(Colors.green),
    ),
    DeveloperSeries(
      year: "2018",
      developers: 5000,
      barColor: charts.ColorUtil.fromDartColor(Colors.green),
    ),
    DeveloperSeries(
      year: "2019",
      developers: 40000,
      barColor: charts.ColorUtil.fromDartColor(Colors.green),
    ),
    DeveloperSeries(
      year: "2020",
      developers: 35000,
      barColor: charts.ColorUtil.fromDartColor(Colors.green),
    ),
    DeveloperSeries(
      year: "2021",
      developers: 45000,
      barColor: charts.ColorUtil.fromDartColor(Colors.green),
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ,
      ),
    );
  }
}

这是一个名为data 的简单列表。列表中的每一个项目都是按照DeveloperSeries 的模型制作的,也就是说每一个项目都有一个年份(year)、开发者的数量(developers)和条形图的颜色(barColor)的属性。

请注意,上面的数据是真实的,所以请随意操作这些数字和颜色。

构建柱状图

我们已经成功地为我们的柱状图创建了数据。现在,让我们来创建条形图本身。为了使我们的项目有条理,我们将把柱状图的代码放在一个单独的文件中。

lib ,创建一个developer_chart.dart 文件。

import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:lib/developer_series.dart';

class DeveloperChart extends StatelessWidget {
  final List<DeveloperSeries> data;

  DeveloperChart({@required this.data});
  @override
  Widget build(BuildContext context) {
    List<charts.Series<DeveloperSeries, String>> series = [
      charts.Series(
        id: "developers",
        data: data,
        domainFn: (DeveloperSeries series, _) => series.year,
        measureFn: (DeveloperSeries series, _) => series.developers,
        colorFn: (DeveloperSeries series, _) => series.barColor
      )
    ];

    Return charts.Barchart(series, animate: true);
  }

}

通过final List<DeveloperSeries> data ,我们定义了一个名为data 的列表,它是我们之前创建的DeveloperSeries 模型形式的数据项的List

列表中的每一个数据项都带有相应的年份、开发人员的数量和条形颜色。

类中的DeveloperChart 构造函数确保在使用条形图类的任何地方,它所需要的数据总是被提供;这是用@required 关键字完成的。

实际的柱状图是在我们的构建部件中创建的。如你所知,所有的柱状图都有几组数据相互对照(在我们的例子中,过去五年和Flutter图表社区获得的开发者数量)。

这些数据组在一起,被称为系列。系列告诉我们Flutter要把哪一组数据放在我们条形图的水平面,哪一组放在垂直面。

然后,我们先前创建的数据列表插入到我们的系列中,并由Flutter适当地使用。

通过List<charts.Series<DeveloperSeries, String>> series ,我们创建了一个名为series 的列表。这个列表的类型为charts.Seriescharts 将Flutter导入我们的项目,Series 函数为Flutter中的柱状图创建系列。

我们刚刚创建的系列是以我们的DeveloperSeries 模型为模型。

我们将在系列中指定的参数包括:id,data,domainFn,measureFn, 和colorFN

  • id 标识了图表
  • data 指向要在柱状图上绘制的项目列表
  • domainFn 指向柱状图水平方向上的数值。
  • measureFn 指向垂直方向上的数值的数量
  • colorFN 指的是条形图的颜色

通过domainFn,measureFn, 和colorFN 函数,我们创建了以Subscriber 系列为参数的函数,创建了它的实例,然后使用这些实例来访问它的不同属性。

developer_chart.dart 文件中的下划线标志着第二个参数是不需要的。

在将我们的系列指向它所需要的所有数据后,我们再使用Flutter的BarChart 函数来创建我们的柱状图。

我们还可以通过简单地将animate 设置为true 来添加一个动画,以获得视觉上的吸引力,这将使图表呈现出一个漂亮的动画。

将柱状图添加到主页上

现在,我们可以将新创建的柱状图添加到我们的主页上并显示。

import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:lib/developer_series.dart';
import 'package:lib/developer_chart.dart';

class HomePage extends StatelessWidget {
  // ...

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: DeveloperChart(
          data: data,
        )
      ),
    );
  }
}

在这里,我们只需在我们的页面主体内调用DeveloperChart 类,并将其指向我们要使用的数据。

为了确保我们的图表能够很好地在屏幕上显示,我们将把它放在一个Card ,在它周围包裹一个容器,并给它设置一个高度和一些填充。

class DeveloperChart extends StatelessWidget {
  final List<DeveloperSeries> data;

  DeveloperChart({@required this.data});
  @override
  Widget build(BuildContext context) {
    List<charts.Series<DeveloperSeries, String>> series = [      charts.Series(        id: "developers",        data: data,        domainFn: (DeveloperSeries series, _) => series.year,        measureFn: (DeveloperSeries series, _) => series.developers,        colorFn: (DeveloperSeries series, _) => series.barColor      )    ];

    return Container(
      height: 300,
      padding: EdgeInsets.all(25),
      child: Card(
        child: Padding(
          padding: const EdgeInsets.all(9.0),
          child: Column(
            children: <Widget>[
              Text(
                "Yearly Growth in the Flutter Community",
                style: Theme.of(context).textTheme.body2,
              ),
              Expanded(
                child: charts.BarChart(series, animate: true),
              )
            ],
          ),
        ),
      ),
    );
  }

}

通过使用expanded widget,我们将我们的柱状图很好地扩展到Card 。上面的Text widget给了我们的柱状图一个标题,让人们知道它是关于什么的。

而且,通过Theme.of(context).textTheme.body2 ,我们将Material Design默认的正文样式应用于我们的标题。

通过padding: const EdgeInsets.all(9.0) ,我们给容纳我们的条形图的卡片在所有边上加了9px的填充。最后,我们将Card 包裹在一个容器中,并给这个容器一个300px的高度和25px的边距。

现在,我们的条形图应该能很好地呈现在我们的屏幕上。

Flutter Bar Chart, Showing Growth Of The Flutter Chart Community Over Five Years With Five Green Bars, With Dates Ranging From 2017 To 2021

创建饼状图

我们也可以使用charts_flutter 包来创建饼图。事实上,我们上面遵循的程序和我们编写的代码可以创建饼图。

要将我们创建的条形图改为饼图,只需将charts.BarChart(series, animate: true) 改为child:( charts.PieChart(series, animate: true)

然后我们就可以在饼图上添加标签。

Expanded(
          child: charts.PieChart(series,
           defaultRenderer: charts.ArcRendererConfig(
            arcRendererDecorators: [
                     charts.ArcLabelDecorator(
                        labelPosition: charts.ArcLabelPosition.inside)
          ])
           animate: true),
)

ArcRendererConfig 函数可以配置饼图的外观,我们可以使用ArcLabelDecorator 函数为饼图添加标签。

labelPosition 指定将标签放在哪里,是放在里面还是外面;在这种情况下,我们指定标签应该放在外面。

Flutter Pie Chart Shows Flutter Chart Community Growth Over Five Years In Green Chart With Dates Ranging From 2017 To 2021

创建折线图

我们可以用创建其他两个图表的同样方法来创建一个折线图。我们只需对我们的数据配置做一个小小的调整。

在我们的系列列表中,List<charts.Series<DeveloperSeries, String>> 变成List<charts.Series<DeveloperSeries, num>> ,因为折线图只对数字起作用。

List<charts.Series<DeveloperSeries, num>> series = [
      charts.Series(
        id: "developers",
        data: data,
        domainFn: (DeveloperSeries series, _) => series.year,
        measureFn: (DeveloperSeries series, _) => series.developers,
        colorFn: (DeveloperSeries series, _) => series.barColor
      )
    ];

现在我们可以把charts.PieChart 改为charts.Linechart ,从而得到我们的折线图。默认情况下,折线图是从原点零开始的。但是我们所关注的年份是从2016年到2021年。因此,这里是如何使我们的折线图跨越这个范围的。

Expanded(
          child: charts.LineChart(series,
           domainAxis: const charts.NumericAxisSpec(
                 tickProviderSpec:
                 charts.BasicNumericTickProviderSpec(zeroBound: false),
                 viewport: charts.NumericExtents(2016.0, 2022.0),
           ),
           animate: true),
)

NumericAxisSpec 函数为图表中的轴设置规格。通过BasicNumericTickProviderSpec 函数,我们将zeroBound 设置为false ,这样我们的图表就不会从原点零开始。

最后,通过NumericExtents 函数,我们设置了我们希望我们的坐标轴所跨越的范围。

Flutter Line Chart With Community Growth Over The Years 2017 To 2021 Indicated By Green Line

总结

本教程的目的是向Flutter开发者展示如何在其应用程序中实现不同的图表。使用谷歌创建的强大的charts_flutter 包,我们能够实现一个柱状图、一个饼状图和一个线形图。

要了解这个包的更多功能,请到pub.dev上查看