【Flutter】fl_chart:グラフ描画ライブラリの使い方を3分で解説!

Flutterでグラフを表示させたい!
Flutterのfl_chartライブラリの使い方を知りたい!

そこで、今回はFlutterでグラフ描画できるライブラリfl_chartの基本的な使い方解説します。

不明点などありましたらお気軽にお問い合わせ下さい。

この記事で分かること!
  • fl_chartって何?
  • fl_chartの使い方

ちなみに、プログラミング初心者は疑問やエラーの解消に時間が掛かり、学習が前に進まなくて挫折することはよくあります。独学でFlutterを学習する場合は、次のことも考えないといけません。

  • 学習の計画
  • スケジュール管理
  • ポートフォリオ作成時に技術選定 など

初心者にとっては大変です。そこで、自走できるまでの手段にスクールを利用するのは1つの手です!Flutterが学べるおすすめスクールはこちらで詳しく解説してます。月2万ほど〜学べるスクールもあるのでご参考にどうぞ。

目次

【Flutter】fl_chartとは?グラフ描画ができる人気ライブラリ

fl_chartはFlutter で人気のグラフ描画ライブラリです。

fl_chartとは

 FL Chart is a highly customizable Flutter chart library that supports Line Chart, Bar Chart, Pie Chart, Scatter Chart, and Radar Chart. 

(直訳)FL Chart は高度にカスタマイズ可能なFlutterチャート ライブラリで、折れ線グラフ、棒グラフ、円グラフ、散布図、レーダー チャートをサポートしています。

引用:pub.dev「fl_chart」

【Flutter】fl_chartでグラフ描画する3つの使い方

fl_chartにおける以下3つの使い方を解説します。

  • 折れ線グラフ
  • 棒グラフ
  • 複合グラフ(折れ線グラフ+棒グラフ)

ライブラリをプロジェクトに追加する

dependencies:
  fl_chart: ^0.55.2

使用するウィジェットをインポートする

import 'package:fl_chart/fl_chart.dart';

Flutter | 折れ線グラフ

上のデモ画面の折れ線グラフの作成方法は以下の通りです。折れ線グラフを表示するにはLineChartを指定します。

クリックするとサンプルコード表示されます。

ファイル構成は以下の通りです。

main.dartファイルの記述は以下の通りです。

import 'package:fl_line_chart_example/lineChart.dart';
import 'package:fl_line_chart_example/pricePoints.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const Home(title: 'Flutter Demo Home Page'),
    );
  }
}

class Home extends StatefulWidget {
  const Home({super.key, required this.title});
  final String title;

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter Chart"),
      ),
      body: content(),
    );
  }

  Widget content() {
    return Center(
      child: Container(
        child: LineChartWidget(pricePoints),
      ),
    );
  }
}

lineChart.dartファイルの記述は以下の通りです。

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'package:flutter/src/foundation/key.dart';
import 'package:flutter/src/widgets/framework.dart';

import 'package:fl_line_chart_example/pricePoints.dart';

class LineChartWidget extends StatelessWidget {
  final List<PricePoint> points;

  const LineChartWidget(this.points, {Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return AspectRatio(
      aspectRatio: 2,
      child: LineChart(LineChartData(lineBarsData: [
        LineChartBarData(
            spots: points.map((point) => FlSpot(point.x, point.y)).toList(),
            isCurved: true,
            dotData: FlDotData(show: false)
        )
      ])),
    );
  }
}

pricePoints.dartファイルの記述は以下の通りです。

import 'package:collection/collection.dart';

class PricePoint {
  final double x;
  final double y;

  PricePoint({required this.x, required this.y});
}

List<PricePoint> get pricePoints {
  final data = <double>[11, 20, 10, 6, 5, 3, 5, 5, 30, 5];
  return data
      .mapIndexed(
          ((index, element) => PricePoint(x: index.toDouble(), y: element)))
      .toList();
}

Flutter | 棒グラフ

棒グラフを表示するにはBarChartを指定します。

クリックするとサンプルコード表示されます。

ファイル構成は以下の通りです。

main.dartファイルは以下の通りです。

import 'package:flutter/material.dart';

import 'barChart.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
       home: const Home(title: 'Flutter Demo Home Page'),
    );
  }
}

class Home extends StatefulWidget {
  const Home({super.key, required this.title});
  final String title;

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("棒グラフデモ"),
      ),
      body: content(),
    );
  }

  Widget content() {
    return Center(
      child: Padding(
        padding: const EdgeInsets.only(top: 25),
        child: BarChartWidget(),
      ),
    );
  }
}

barChart.dartファイルは以下の通りです。

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'package:flutter/src/widgets/framework.dart';

class BarChartWidget extends StatelessWidget {

  // 棒グラフの棒の横幅
  static const double barWidth = 20.0;

  // グラフタイトルのラベル書式
  final TextStyle _labelStyle = const TextStyle(fontSize: 16, fontWeight: FontWeight.w800);

  // ダミーデータ
  final blogLog = <double>[11, 17, 10, 6, 5, 3, 5, 3, 4, 3, 16, 15];

  @override
  Widget build(BuildContext context) {
    return AspectRatio(
      aspectRatio: 2,
      child: BarChart(
        BarChartData(maxY: 20, //Y軸の最大値を指定

            // 棒グラフの位置
            alignment: BarChartAlignment.spaceEvenly,

            // 棒グラフタッチ時の動作設定
            barTouchData: BarTouchData(
                touchTooltipData: BarTouchTooltipData(
                  tooltipBgColor: Colors.black,
                )
            ),

            // グラフタイトルのパラメータ
            titlesData: FlTitlesData(
              show: true,
              //右タイトル
              rightTitles:AxisTitles(
                  sideTitles: SideTitles(showTitles: false)
              ),
              //上タイトル
              topTitles: AxisTitles(
                sideTitles: SideTitles(showTitles: false),
              ),
              //下タイトル
              bottomTitles: AxisTitles(
                axisNameWidget: Text('ブログ運営年月',style: _labelStyle,),
                axisNameSize: 40,
                sideTitles: SideTitles(
                  showTitles: true,
                ),
              ),
              // 左タイトル
              leftTitles: AxisTitles(
                axisNameWidget: Container(
                    alignment: Alignment.topCenter,
                    child: Text('記事数',style: _labelStyle,)),
                axisNameSize: 25,
                sideTitles: SideTitles(
                  showTitles: true,
                ),
              ),
            ),

            // 外枠表の線を表示/非表示
            borderData: FlBorderData(
                border: const Border(
                  top: BorderSide.none,
                  right: BorderSide.none,
                  left: BorderSide(width: 1),
                  bottom: BorderSide(width: 1),
                )),


            // barGroups: 棒グラフのグループを表す
            // BarChartGroupData: 棒グラフの1つのグループを表す
            // X : 横軸
            // barRods: 棒グラフのデータを含むBarRodクラスのリスト
            // BarChartRodData
            // toY : 高さ
            // width : 棒の幅
            barGroups: [
              BarChartGroupData(x: 2, barRods: [
                BarChartRodData(toY: blogLog[0], width: barWidth),
              ]),
              BarChartGroupData(x: 3, barRods: [
                BarChartRodData(toY: blogLog[1], width: barWidth),
              ]),
              BarChartGroupData(x: 4, barRods: [
                BarChartRodData(toY: blogLog[2], width: barWidth),
              ]),
              BarChartGroupData(x: 5, barRods: [
                BarChartRodData(toY: blogLog[3], width: barWidth),
              ]),
              BarChartGroupData(x: 6, barRods: [
                BarChartRodData(toY: blogLog[4], width: barWidth),
              ]),
              BarChartGroupData(x: 7, barRods: [
                BarChartRodData(toY: blogLog[5], width: barWidth),
              ]),
              BarChartGroupData(x: 8, barRods: [
                BarChartRodData(toY: blogLog[6], width: barWidth),
              ]),
              BarChartGroupData(x: 9, barRods: [
                BarChartRodData(toY: blogLog[7], width: barWidth),
              ]),
              BarChartGroupData(x: 10, barRods: [
                BarChartRodData(toY: blogLog[8], width: barWidth),
              ]),
              BarChartGroupData(x: 11, barRods: [
                BarChartRodData(toY: blogLog[9], width: barWidth),
              ]),
              BarChartGroupData(x: 12, barRods: [
                BarChartRodData(toY: blogLog[10], width: barWidth),
              ]),
              BarChartGroupData(x: 1, barRods: [
                BarChartRodData(toY: blogLog[11], width: barWidth),
              ]),
            ]),
      ),
    );
  }
}

Flutter | 複合グラフ(折れ線グラフ+棒グラフ)

fl_chartで複合グラフの使用方法を公式ページから調べましたが、具体的な方法は見つかりませんでした。
なので、棒グラフと折れ線グラフをStackウィジェットで重ねて描画しました。

クリックするとサンプルコード表示されます。
import 'package:flutter/material.dart';
import 'package:fl_chart/fl_chart.dart';

void main() => runApp(StatelessDemo());

class StatelessDemo extends StatelessWidget {

  // グラフタイトルのラベル書式
  final TextStyle _labelStyle =
      const TextStyle(fontSize: 16, fontWeight: FontWeight.w800);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('複合グラフデモ'),
        ),
        body: Container(
          padding: EdgeInsets.all(50),
          child: Stack(
             children: [
              Align(
                alignment: const Alignment(0.0, 0.0),
                  child: Padding(
                    padding: const EdgeInsets.all(22.0),
                    child: LineChart(LineChartData(

                          // グラフのx軸y軸の表示数
                          minX: 0.0,
                          maxX: 5.8,
                          minY: 0.0,
                          maxY: 10.0,

                          // 背景のグリッド線の設定
                          gridData: FlGridData(
                            show: true,                          // 背景のグリッド線の有無
                            drawVerticalLine: true,              // 水平方向のグリッド線の有無
                            horizontalInterval: 5.0,             // 背景グリッドの横線間隔
                            verticalInterval: 2.0,               // 背景グリッドの縦線間隔
                            getDrawingHorizontalLine: (value) {  // 背景グリッドの横線設定
                              return FlLine(
                                color: Color(0xff37434d),        // 背景横線の色
                                strokeWidth: 1.0,                // 背景横線の太さ
                              );
                            },
                            getDrawingVerticalLine: (value) {    // 背景グリッドの縦線設定
                              return FlLine(
                                color: Color(0xff37434d),        // 背景縦線の色
                                strokeWidth: 1.0,                // 背景縦線の太さ
                              );
                            },
                          ),

                          // 外枠の線
                          borderData: FlBorderData(
                              border: const Border(
                            top: BorderSide.none,
                            right: BorderSide.none,
                                left: BorderSide(width: 1),
                                bottom: BorderSide(width: 1),
                          )),

                        // グラフタイトル
                        titlesData: FlTitlesData(
                          show: true,
                          //右タイトル
                          rightTitles:AxisTitles(sideTitles: SideTitles(showTitles: false)),
                          //上タイトル
                          topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false),),
                          //下タイトル
                          bottomTitles: AxisTitles(sideTitles: SideTitles(showTitles: false,),),
                          // 左タイトル
                          leftTitles: AxisTitles(sideTitles: SideTitles(showTitles: false,),),
                        ),

                          // データ追加
                          lineBarsData: [
                            LineChartBarData(
                                spots: [
                                  FlSpot(1.0, 1.0),//x:y
                                  FlSpot(2.0, 5.0),
                                  FlSpot(3.0, 2.0),
                                  FlSpot(4.0, 5.0),
                                  FlSpot(5.0, 0.0),
                                ],

                                isCurved: true, // 曲線or折れ線
                                barWidth: 5.0, // 線の幅
                                color: Colors.red[300], // 線の色

                                // ドット指定
                                dotData: FlDotData(show: false)
                            )
                          ]

                      )),
                  ),
              ),
               Align(
                 alignment: const Alignment(0.0, 0.0),
                child: BarChart(
                    BarChartData(

                  // グラフのx軸y軸のの表示数
                    minY: 0.0,
                    maxY: 10.0,

                    // タイトル
                    titlesData: FlTitlesData(
                      show: true,
                      //右タイトル
                      rightTitles:AxisTitles(sideTitles: SideTitles(showTitles: false)),
                      //上タイトル
                      topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false),),
                      //下タイトル
                      bottomTitles: AxisTitles(
                        // axisNameWidget: Text('ブログ運営年月',style: _labelStyle,),
                        // axisNameSize: 40,
                        sideTitles: SideTitles(showTitles: true,),),
                      // 左タイトル
                      leftTitles: AxisTitles(
                        // axisNameWidget: Text('記事数',style: _labelStyle,),
                        // axisNameSize: 25,
                        sideTitles: SideTitles(showTitles: true,),),
                    ),

                    // 背景のグリッド線の設定
                    gridData: FlGridData(
                      show: false,                         // 背景のグリッド線の有無
                      drawVerticalLine: true,              // 水平方向のグリッド線の有無
                      horizontalInterval: 1.0,             // 背景グリッドの横線間隔
                      verticalInterval: 1.0,               // 背景グリッドの縦線間隔
                      getDrawingHorizontalLine: (value) {  // 背景グリッドの横線設定
                        return FlLine(
                          color: Color(0xff37434d),        // 背景横線の色
                          strokeWidth: 1.0,                // 背景横線の太さ
                        );
                      },
                      getDrawingVerticalLine: (value) {    // 背景グリッドの縦線設定
                        return FlLine(
                          color: Color(0xff37434d),        // 背景縦線の色
                          strokeWidth: 1.0,                // 背景縦線の太さ
                        );
                      },
                    ),

                    // 外枠表の線
                    borderData: FlBorderData(
                        border: const Border(
                          top: BorderSide.none,
                          right: BorderSide.none,
                          left: BorderSide(width: 1),
                          bottom: BorderSide(width: 1),
                    )),

                    // データ追加
                    barGroups: [
                      BarChartGroupData(x: 1, barRods: [BarChartRodData(toY: 8, width: 10),]),
                      BarChartGroupData(x: 2, barRods: [BarChartRodData(toY: 3, width: 10),]),
                      BarChartGroupData(x: 3, barRods: [BarChartRodData(toY: 5, width: 10),]),
                      BarChartGroupData(x: 4, barRods: [BarChartRodData(toY: 8, width: 10),]),
                      BarChartGroupData(x: 5, barRods: [BarChartRodData(toY: 7, width: 10),]),
                    ]

                )),
              ),
            ],
    ),
        ),
      ),
    );
  }
}

ちなみに、syncfusion_flutter_chartsでは以下のような複合グラフ作成も対応してます。

ただ、商用パッケージなので、利用にはSyncfusion 商用ライセンスまたは無料の Syncfusion コミュニティ ライセンスが必要です。

無料のライセンス対象は?

年間総収益が 100 万USドル未満で、開発者が 5 人以下の企業および個人。

Who is eligible?
Companies and individuals with less than $1 million USD in annual gross revenue and 5 or fewer developers.
Note: An entity or organization may not have ever received more than $3,000,000 USD in capital from an outside source, such as private equity or venture capital, in order to be eligible for the Community License.
引用: Syncfusion コミュニティ
焼き芋

個人開発で年間収益が1億円以上も稼げることはまずないので、大抵の個人開発者は利用できます。

Syncfusionのライブラリを利用したグラフの作り方はコチラの記事で解説してます。

まとめ:fl_chartはグラフ描画が簡単にできて便利!

今回Flutterでグラフの描画ができるライブラリfl_chartの基本的な使い方解説しました。

グラフ描画できるライブラリは1つか2つ押さえおくと便利です!個人アプリ開発時に表現の幅が広がるので、ぜひ押さえておきましょう!

Flutterエンジニアになるには?

初心者が中級者レベルのFlutterエンジニアなるまでの進め方をまとめました。

Flutterの学習方法を知る

Flutter を動画で学ぶ(Udemy)

Flutter をスクールで学ぶ

Flutterの仕事を探す

おまけFlutter入門の完全ガイド

Flutter/Dartの基礎一覧

Flutter/Dartの入門知識として押さえておきたい内容をまとめました。学習のご参考にどうぞ。

Widget一覧

画面レイアウト

ボタン

入力・出力

ページ遷移

状態管理

非同期処理

Dartの基本文法

ライブラリ使い方

目次