bezier_chart 1.0.17+1

  • Readme
  • Changelog
  • Example
  • Installing
  • 96

Bezier Chart #

pub package Codemagic build status

A beautiful bezier line chart widget for flutter that is highly interactive and configurable.

Aeyrium Inc. is a provider of innovative software solutions for the business and commercial aviation

drawing drawing

drawing drawing

Features #

  • Multi bezier lines
  • Allow numbers and datetimes
  • Gestures support like touch, pinch/zoom, scrolling
  • Highly customizable

Instructions #

  • Long press and drag to display the indicator
  • Tap to dismiss the indicator
  • When using chart Scale different from Custom, you can change between WEEKLY, MONTHLY, YEARLY using pinch/zoom when the indicator is not visible.

Getting started #

You should ensure that you add the dependency in your flutter project.

dependencies:
  bezier_chart: "^1.0.16"

You should then run flutter packages upgrade or update your packages in IntelliJ.

Example Project #

There is a example project in the example folder. Check it out. Otherwise, keep reading to get up and running.

Usage #

Custom Numbers

  Widget sample1(BuildContext context) {
  return Center(
    child: Container(
      color: Colors.red,
      height: MediaQuery.of(context).size.height / 2,
      width: MediaQuery.of(context).size.width * 0.9,
      child: BezierChart(
        bezierChartScale: BezierChartScale.CUSTOM,
        xAxisCustomValues: const [0, 5, 10, 15, 20, 25, 30, 35],
        series: const [
          BezierLine(
            data: const [
              DataPoint<double>(value: 10, xAxis: 0),
              DataPoint<double>(value: 130, xAxis: 5),
              DataPoint<double>(value: 50, xAxis: 10),
              DataPoint<double>(value: 150, xAxis: 15),
              DataPoint<double>(value: 75, xAxis: 20),
              DataPoint<double>(value: 0, xAxis: 25),
              DataPoint<double>(value: 5, xAxis: 30),
              DataPoint<double>(value: 45, xAxis: 35),
            ],
          ),
        ],
        config: BezierChartConfig(
          verticalIndicatorStrokeWidth: 3.0,
          verticalIndicatorColor: Colors.black26,
          showVerticalIndicator: true,
          backgroundColor: Colors.red,
          snap: false,
        ),
      ),
    ),
  );
}

Custom Numbers multiline

Widget sample2(BuildContext context) {
  return Center(
    child: Container(
      color: Colors.red,
      height: MediaQuery.of(context).size.height / 2,
      width: MediaQuery.of(context).size.width,
      child: BezierChart(
        bezierChartScale: BezierChartScale.CUSTOM,
        xAxisCustomValues: const [0, 3, 10, 15, 20, 25, 30, 35],
        series: const [
          BezierLine(
            label: "Custom 1",
            data: const [
              DataPoint<double>(value: 10, xAxis: 0),
              DataPoint<double>(value: 130, xAxis: 5),
              DataPoint<double>(value: 50, xAxis: 10),
              DataPoint<double>(value: 150, xAxis: 15),
              DataPoint<double>(value: 75, xAxis: 20),
              DataPoint<double>(value: 0, xAxis: 25),
              DataPoint<double>(value: 5, xAxis: 30),
              DataPoint<double>(value: 45, xAxis: 35),
            ],
          ),
          BezierLine(
            lineColor: Colors.blue,
            lineStrokeWidth: 2.0,
            label: "Custom 2",
            data: const [
              DataPoint<double>(value: 5, xAxis: 0),
              DataPoint<double>(value: 50, xAxis: 5),
              DataPoint<double>(value: 30, xAxis: 10),
              DataPoint<double>(value: 30, xAxis: 15),
              DataPoint<double>(value: 50, xAxis: 20),
              DataPoint<double>(value: 40, xAxis: 25),
              DataPoint<double>(value: 10, xAxis: 30),
              DataPoint<double>(value: 30, xAxis: 35),
            ],
          ),
          BezierLine(
            lineColor: Colors.black,
            lineStrokeWidth: 2.0,
            label: "Custom 3",
            data: const [
              DataPoint<double>(value: 5, xAxis: 0),
              DataPoint<double>(value: 10, xAxis: 5),
              DataPoint<double>(value: 35, xAxis: 10),
              DataPoint<double>(value: 40, xAxis: 15),
              DataPoint<double>(value: 40, xAxis: 20),
              DataPoint<double>(value: 40, xAxis: 25),
              DataPoint<double>(value: 9, xAxis: 30),
              DataPoint<double>(value: 11, xAxis: 35),
            ],
          ),
        ],
        config: BezierChartConfig(
          verticalIndicatorStrokeWidth: 2.0,
          verticalIndicatorColor: Colors.black12,
          showVerticalIndicator: true,
          contentWidth: MediaQuery.of(context).size.width * 2,
          backgroundColor: Colors.red,
        ),
      ),
    ),
  );
}

Weekly Chart

Widget sample3(BuildContext context) {
  final fromDate = DateTime(2019, 05, 22);
  final toDate = DateTime.now();

  final date1 = DateTime.now().subtract(Duration(days: 2));
  final date2 = DateTime.now().subtract(Duration(days: 3));

  return Center(
    child: Container(
      color: Colors.red,
      height: MediaQuery.of(context).size.height / 2,
      width: MediaQuery.of(context).size.width,
      child: BezierChart(
        fromDate: fromDate,
        bezierChartScale: BezierChartScale.WEEKLY,
        toDate: toDate,
        selectedDate: toDate,
        series: [
          BezierLine(
            label: "Duty",
            onMissingValue: (dateTime) {
              if (dateTime.day.isEven) {
                return 10.0;
              }
              return 5.0;
            },
            data: [
              DataPoint<DateTime>(value: 10, xAxis: date1),
              DataPoint<DateTime>(value: 50, xAxis: date2),
            ],
          ),
        ],
        config: BezierChartConfig(
          verticalIndicatorStrokeWidth: 3.0,
          verticalIndicatorColor: Colors.black26,
          showVerticalIndicator: true,
          verticalIndicatorFixedPosition: false,
          backgroundColor: Colors.red,
          footerHeight: 30.0,
        ),
      ),
    ),
  );
}

Monthly Chart

Widget sample4(BuildContext context) {
  final fromDate = DateTime(2018, 11, 22);
  final toDate = DateTime.now();

  final date1 = DateTime.now().subtract(Duration(days: 2));
  final date2 = DateTime.now().subtract(Duration(days: 3));

  final date3 = DateTime.now().subtract(Duration(days: 35));
  final date4 = DateTime.now().subtract(Duration(days: 36));

  final date5 = DateTime.now().subtract(Duration(days: 65));
  final date6 = DateTime.now().subtract(Duration(days: 64));

  return Center(
    child: Container(
      color: Colors.red,
      height: MediaQuery.of(context).size.height / 2,
      width: MediaQuery.of(context).size.width,
      child: BezierChart(
        bezierChartScale: BezierChartScale.MONTHLY,
        fromDate: fromDate,
        toDate: toDate,
        selectedDate: toDate,
        series: [
          BezierLine(
            label: "Duty",
            onMissingValue: (dateTime) {
              if (dateTime.month.isEven) {
                return 10.0;
              }
              return 5.0;
            },
            data: [
              DataPoint<DateTime>(value: 10, xAxis: date1),
              DataPoint<DateTime>(value: 50, xAxis: date2),
              DataPoint<DateTime>(value: 20, xAxis: date3),
              DataPoint<DateTime>(value: 80, xAxis: date4),
              DataPoint<DateTime>(value: 14, xAxis: date5),
              DataPoint<DateTime>(value: 30, xAxis: date6),
            ],
          ),
        ],
        config: BezierChartConfig(
          verticalIndicatorStrokeWidth: 3.0,
          verticalIndicatorColor: Colors.black26,
          showVerticalIndicator: true,
          verticalIndicatorFixedPosition: false,
          backgroundColor: Colors.red,
          footerHeight: 30.0,
        ),
      ),
    ),
  );
}

Yearly Chart

Widget sample5(BuildContext context) {
  final fromDate = DateTime(2012, 11, 22);
  final toDate = DateTime.now();

  final date1 = DateTime.now().subtract(Duration(days: 2));
  final date2 = DateTime.now().subtract(Duration(days: 3));

  final date3 = DateTime.now().subtract(Duration(days: 300));
  final date4 = DateTime.now().subtract(Duration(days: 320));

  final date5 = DateTime.now().subtract(Duration(days: 650));
  final date6 = DateTime.now().subtract(Duration(days: 652));

  return Center(
    child: Container(
      color: Colors.red,
      height: MediaQuery.of(context).size.height / 2,
      width: MediaQuery.of(context).size.width,
      child: BezierChart(
        bezierChartScale: BezierChartScale.YEARLY,
        fromDate: fromDate,
        toDate: toDate,
        selectedDate: toDate,
        series: [
          BezierLine(
            label: "Duty",
            onMissingValue: (dateTime) {
              if (dateTime.year.isEven) {
                return 20.0;
              }
              return 5.0;
            },
            data: [
              DataPoint<DateTime>(value: 10, xAxis: date1),
              DataPoint<DateTime>(value: 50, xAxis: date2),
              DataPoint<DateTime>(value: 100, xAxis: date3),
              DataPoint<DateTime>(value: 100, xAxis: date4),
              DataPoint<DateTime>(value: 40, xAxis: date5),
              DataPoint<DateTime>(value: 47, xAxis: date6),
            ],
          ),
          BezierLine(
            label: "Flight",
            lineColor: Colors.black26,
            onMissingValue: (dateTime) {
              if (dateTime.month.isEven) {
                return 10.0;
              }
              return 3.0;
            },
            data: [
              DataPoint<DateTime>(value: 20, xAxis: date1),
              DataPoint<DateTime>(value: 30, xAxis: date2),
              DataPoint<DateTime>(value: 150, xAxis: date3),
              DataPoint<DateTime>(value: 80, xAxis: date4),
              DataPoint<DateTime>(value: 45, xAxis: date5),
              DataPoint<DateTime>(value: 45, xAxis: date6),
            ],
          ),
        ],
        config: BezierChartConfig(
          verticalIndicatorStrokeWidth: 3.0,
          verticalIndicatorColor: Colors.black26,
          showVerticalIndicator: true,
          verticalIndicatorFixedPosition: false,
          backgroundGradient: LinearGradient(
            colors: [
              Colors.red[300],
              Colors.red[400],
              Colors.red[400],
              Colors.red[500],
              Colors.red,
            ],
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
          ),
          footerHeight: 30.0,
        ),
      ),
    ),
  );
}

API

In this table, you can find all attributes provided by BezierChartConfig:

AttributeDefault valueDescription
showVerticalIndicatortruetrue if you want to display the vertical indicator
verticalIndicatorColorColors.black
verticalIndicatorStrokeWidth2.0width of the line used for the vertical indicator
verticalIndicatorFixedPositionfalsetrue if you want to keep the info indicator in a fixed position
verticalLineFullHeighttrue if you want to display the vertical line in full height
bubbleIndicatorColorColors.whiteColor of the bubble indicator, it's white by default
bubbleIndicatorTitleStyleconst TextStyle()TextStyle for the title displayed inside the bubble indicator
bubbleIndicatorValueStyleconst TextStyle()TextStyle for the value displayed inside the bubble indicator
bubbleIndicatorValueFormatnullNumberFormat for the value displayed inside the bubble indicator
bubbleIndicatorLabelStyleconst TextStyle()TextStyle for the label displayed inside the bubble indicator
backgroundColorColors.transparentColor of the background of the chart
backgroundGradientGradient of the background of the chart
displayYAxisfalsetrue if you want to display the value of the Y axis, [false] by default
stepsYAxisIf [displayYAxis] is true, then you can set a positive value to display the steps of Y axis values.<br/>e.g 1: stepsYAxis : 5 , if your maxValue is 100, then the Y values should be: [0,5,10,15 .... 100] <br/>e.g 2: stepsYAxis : 10 , if your maxValue is 100, then the Y values should be: [10,20,30,40 .... 100]
startYAxisFromNonZeroValuetruetrue if you want to start the values of Y axis from the minimum value of your Y values
yAxisTextStyleTextStyle of the text of the Y Axis values
xAxisTextStyleTextStyle of the text of the X Axis values
footerHeight35.0Height of the footer
showDataPointstruetrue if you want to display the data points
snaptruetrue if you want to snap between each data point
pinchZoomtruetrue if you want to enable pinch Zoom for bezierChartScale of date types<br/>Pinch and zoom is used to switch beetwen charts of date types
contentWidthIf the contentWidth is upper than the current width then the content will be scrollable (only valid for bezierChartScale = CUSTOM)
displayLinesXAxisfalsetrue if you want to display a vertical line on each X data point, it only works when there is one BezierLine
xLinesColorColors.greyColor for the vertical line in each X point, only works when displayLinesXAxis is true
displayDataPointWhenNoValuetruetrue if you want do display the dot when there is no value specified (The values inside onMissingValue)
physicsconst AlwaysScrollableScrollPhysics()The physics for horizontal ScrollView
updatePositionOnTapfalsetrue if you want do update bubble info on tap action instead of long press. This option will disable tap to hide bubble action

Aeyrium Inc

You can follow me on twitter @diegoveloper

[1.0.17 - 1.0.17+1] #

  • Format bubble value and updatePositionOnTap were added. Thanks @ltdangkhoa.

[1.0.16] #

  • dataPointFillColor and dataPointStrokeColor were added in BezierLine.
  • verticalLineFullHeight was added in BezierChartConfig.
  • onScaleChanged was added in BezierChart to notify when the scale was changed.
  • Issue related to updating the chart with new data fixed. https://github.com/aeyrium/bezier-chart/issues/62
  • Web support was added

[1.0.15] #

  • Fixed a bug related to BezierChartScale.WEEKLY
  • new property added bezierChartAggregation for BezierChartConfig
  • if datapoints now overlap the chosen aggregation method is used -> Supported are: AVERAGE, SUM, FIRST, COUNT

[1.0.14] #

  • Fixed a bug related to stepsYAxis value
  • new property added displayDataPointWhenNoValue for BezierChartConfig
  • new property added physics for BezierChartConfig
  • Added bubbleLabelValueBuilder and bubbleLabelDateTimeBuilder callbacks

[1.0.13] #

  • selectedValue was added for BezierChartScale.CUSTOM

[1.0.12] #

  • verticalIndicatorFixedPosition from BezierChartConfig was changed false by default.
  • stepsYAxis was added to BezierChartConfig , it works only if displayYAxis is [true]. e.g: stepsYAxis : 5 , if your maxValue is 100, then the Y values should be: [0,5,10,15 .... 100] (Check sample1 or sample7)
  • bubbleIndicatorLabelStyle, bubbleIndicatorTitleStyle and bubbleIndicatorValuetyle were added inside BezierChartConfig to allow customization for the bubble indicator panel.
  • bugs fixing

[1.0.11] #

  • onIndicatorVisible callback was added to check when the indicator is visible or not
  • onValueSelected was added , it displays the current double value selected by the indicator (if the chart is CUSTOM).
  • onDateTimeSelected was added, it displays the current DateTime selected by the indicator (if the chart is Date type).
  • New date type chart added BezierChartScale.HOURLY , doesn't support zoom.

[1.0.10] #

  • Fixed pinchZoom for BezierChartConfig.
  • footerDateTimeBuilder was added as optional inside BezierChart, it allows you to display custom X footer for each DateTime value.

[1.0.9] #

  • Optimizing for loops removing unnecessary convertion from Iterable to List.
  • startYAxisFromNonZeroValue property was added, if you are displaying the Y Axis then your chart will start from your lower value, if you set it to false, it will start from zero.
  • displayLinesXAxis and xLinesColor were added to display a vertical line on each X data point, it only works when there is one BezierLine.

[1.0.8] #

  • Chart starts from the first data point, not from zero.
  • displayYAxis was added (false by default).
  • footerColor was removed from BezierChartConfig, now you can use xAxisTextStyle or yAxisTextStyle both are TextStyle.

[1.0.1 - 1.0.7] - Added example documentation #

  • Added an example README.md for the bezier_chart package.
  • Added a repository url to the pubspec

[1.0.0] - First release #

  • First release of our beautiful bezier_chart package.

example/lib/main.dart

import 'package:bezier_chart/bezier_chart.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart' as intl;

import 'sample10.dart';
import 'sample12.dart';
import 'sample13.dart';
import 'sample14.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  _onTap(BuildContext context, Widget widget) {
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (_) => Scaffold(
          appBar: AppBar(),
          body: widget,
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Bezier Chart Sample"),
      ),
      body: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ListTile(
              title: Text("Sample 1"),
              subtitle: Text("Number Chart"),
              onTap: () => _onTap(
                context,
                sample1(context),
              ),
            ),
            ListTile(
              title: Text("Sample 2"),
              subtitle: Text("Number Chart/ multi curves"),
              onTap: () => _onTap(
                context,
                sample2(context),
              ),
            ),
            ListTile(
              title: Text("Sample 3"),
              subtitle: Text("Weekly Chart"),
              onTap: () => _onTap(
                context,
                sample3(context),
              ),
            ),
            ListTile(
              title: Text("Sample 4"),
              subtitle: Text("Montly Chart"),
              onTap: () => _onTap(
                context,
                sample4(context),
              ),
            ),
            ListTile(
              title: Text("Sample 5"),
              subtitle: Text("Yearly Chart"),
              onTap: () => _onTap(
                context,
                sample5(context),
              ),
            ),
            ListTile(
              title: Text("Sample 6"),
              subtitle: Text("Main Chart"),
              onTap: () => _onTap(
                context,
                sample6(context),
              ),
            ),
            ListTile(
              title: Text("Sample 7"),
              subtitle: Text("Custom Chart - Number"),
              onTap: () => _onTap(
                context,
                sample7(context),
              ),
            ),
            ListTile(
              title: Text("Sample 8"),
              subtitle: Text("Hourly Chart"),
              onTap: () => _onTap(
                context,
                sample8(context),
              ),
            ),
            ListTile(
              title: Text("Sample 9"),
              subtitle: Text("BezierChartScale.WEEKLY same day"),
              onTap: () => _onTap(
                context,
                sample9(context),
              ),
            ),
            ListTile(
              title: Text("Sample 10"),
              subtitle: Text("Async Custom Chart - Number"),
              onTap: () => _onTap(
                context,
                Sample10(),
              ),
            ),
            ListTile(
              title: Text("Sample 11"),
              subtitle: Text("Custom Bubble Label Example"),
              onTap: () => _onTap(
                context,
                sample11(context),
              ),
            ),
            ListTile(
              title: Text("Sample 12"),
              subtitle: Text("Dynamic date range"),
              onTap: () => Navigator.of(context)
                  .push(MaterialPageRoute(builder: (context) => Sample12())),
            ),
            ListTile(
              title: Text("Sample 13"),
              subtitle: Text("Dynamic date range"),
              onTap: () => Navigator.of(context)
                  .push(MaterialPageRoute(builder: (context) => Sample13())),
            ),
            ListTile(
              title: Text("Sample 14"),
              subtitle: Text(
                  "Sample with updatePositionOnTap & format indicator value"),
              onTap: () => Navigator.of(context)
                  .push(MaterialPageRoute(builder: (context) => Sample14())),
            ),
          ],
        ),
      ),
    );
  }
}

//SAMPLE CUSTOM VALUES
Widget sample1(BuildContext context) {
  return Container(
    decoration: BoxDecoration(
      gradient: LinearGradient(
        colors: [
          Colors.black54,
          Colors.black87,
          Colors.black87,
          Colors.black,
        ],
        begin: Alignment.topCenter,
        end: Alignment.bottomCenter,
      ),
    ),
    child: Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Text(
          "Bezier Chart - Numbers",
          style: TextStyle(
            color: Colors.white,
            fontSize: 28,
            fontWeight: FontWeight.w700,
          ),
        ),
        Center(
          child: Card(
            elevation: 12,
            child: Container(
              height: MediaQuery.of(context).size.height / 2,
              width: MediaQuery.of(context).size.width * 0.9,
              child: BezierChart(
                bezierChartScale: BezierChartScale.CUSTOM,
                selectedValue: 30,
                xAxisCustomValues: const [0, 5, 10, 15, 20, 25, 30, 35],
                footerValueBuilder: (double value) {
                  return "${formatAsIntOrDouble(value)}\ndays";
                },
                series: const [
                  BezierLine(
                    label: "m",
                    data: const [
                      DataPoint<double>(value: 10, xAxis: 0),
                      DataPoint<double>(value: 130, xAxis: 5),
                      DataPoint<double>(value: 50, xAxis: 10),
                      DataPoint<double>(value: 150, xAxis: 15),
                      DataPoint<double>(value: 75, xAxis: 20),
                      DataPoint<double>(value: 0, xAxis: 25),
                      DataPoint<double>(value: 5, xAxis: 30),
                      DataPoint<double>(value: 45, xAxis: 35),
                    ],
                  ),
                ],
                config: BezierChartConfig(
                  startYAxisFromNonZeroValue: false,
                  bubbleIndicatorColor: Colors.white.withOpacity(0.9),
                  footerHeight: 40,
                  verticalIndicatorStrokeWidth: 3.0,
                  verticalIndicatorColor: Colors.black26,
                  showVerticalIndicator: true,
                  verticalIndicatorFixedPosition: false,
                  displayYAxis: true,
                  stepsYAxis: 10,
                  backgroundGradient: LinearGradient(
                    colors: [
                      Colors.red[300],
                      Colors.red[400],
                      Colors.red[400],
                      Colors.red[500],
                      Colors.red,
                    ],
                    begin: Alignment.topCenter,
                    end: Alignment.bottomCenter,
                  ),
                  snap: true,
                ),
              ),
            ),
          ),
        ),
      ],
    ),
  );
}

Widget sample2(BuildContext context) {
  return Container(
    color: Colors.black87,
    child: Center(
      child: Card(
        elevation: 20,
        margin: EdgeInsets.all(8.0),
        child: Container(
          height: MediaQuery.of(context).size.height / 2,
          width: MediaQuery.of(context).size.width,
          child: BezierChart(
            bezierChartScale: BezierChartScale.CUSTOM,
            xAxisCustomValues: const [0, 3, 10, 15, 20, 25, 30, 35],
            footerValueBuilder: (double value) {
              return "${value.toInt()}\nHrs";
            },
            series: const [
              BezierLine(
                label: "Custom 1",
                lineStrokeWidth: 4.0,
                data: const [
                  DataPoint<double>(value: 10, xAxis: 0),
                  DataPoint<double>(value: 130, xAxis: 5),
                  DataPoint<double>(value: 50, xAxis: 10),
                  DataPoint<double>(value: 150, xAxis: 15),
                  DataPoint<double>(value: 75, xAxis: 20),
                  DataPoint<double>(value: 0, xAxis: 25),
                  DataPoint<double>(value: 5, xAxis: 30),
                  DataPoint<double>(value: 45, xAxis: 35),
                ],
              ),
              BezierLine(
                lineColor: Colors.blue,
                lineStrokeWidth: 4.0,
                label: "Custom 2",
                data: const [
                  DataPoint<double>(value: 5, xAxis: 0),
                  DataPoint<double>(value: 50, xAxis: 5),
                  DataPoint<double>(value: 30, xAxis: 10),
                  DataPoint<double>(value: 30, xAxis: 15),
                  DataPoint<double>(value: 50, xAxis: 20),
                  DataPoint<double>(value: 40, xAxis: 25),
                  DataPoint<double>(value: 10, xAxis: 30),
                  DataPoint<double>(value: 30, xAxis: 35),
                ],
              ),
              BezierLine(
                lineColor: Colors.red,
                lineStrokeWidth: 4.0,
                label: "Custom 3",
                data: const [
                  DataPoint<double>(value: 5, xAxis: 0),
                  DataPoint<double>(value: 10, xAxis: 5),
                  DataPoint<double>(value: 35, xAxis: 10),
                  DataPoint<double>(value: 40, xAxis: 15),
                  DataPoint<double>(value: 40, xAxis: 20),
                  DataPoint<double>(value: 40, xAxis: 25),
                  DataPoint<double>(value: 9, xAxis: 30),
                  DataPoint<double>(value: 11, xAxis: 35),
                ],
              ),
            ],
            config: BezierChartConfig(
              verticalIndicatorStrokeWidth: 2.0,
              verticalIndicatorColor: Colors.black12,
              showVerticalIndicator: true,
              verticalIndicatorFixedPosition: false,
              contentWidth: MediaQuery.of(context).size.width * 1.5,
              xAxisTextStyle: TextStyle(
                color: Colors.white60,
                fontSize: 19,
              ),
              footerHeight: 45,
              backgroundGradient: LinearGradient(
                colors: [
                  Colors.purpleAccent[400],
                  Colors.purpleAccent[400],
                  Colors.purpleAccent[700],
                  Colors.purpleAccent[700],
                  Colors.purpleAccent,
                ],
                begin: Alignment.topCenter,
                end: Alignment.bottomCenter,
              ),
            ),
          ),
        ),
      ),
    ),
  );
}

//SAMPLE DATE - WEEKLY

Widget sample3(BuildContext context) {
  final fromDate = DateTime(2019, 05, 22);
  final toDate = DateTime.now();
  final date1 = DateTime.now().subtract(Duration(days: 2));
  final date2 = DateTime.now().subtract(Duration(days: 3));
  return Center(
    child: Container(
      color: Colors.red,
      height: MediaQuery.of(context).size.height / 2,
      width: MediaQuery.of(context).size.width,
      child: BezierChart(
        fromDate: fromDate,
        bezierChartScale: BezierChartScale.WEEKLY,
        toDate: toDate,
        onIndicatorVisible: (val) {
          print("Indicator Visible :$val");
        },
        onDateTimeSelected: (datetime) {
          print("selected datetime: $datetime");
        },
        onScaleChanged: (scale) {
          print("Scale: $scale");
        },
        selectedDate: toDate,
        //this is optional
        footerDateTimeBuilder: (DateTime value, BezierChartScale scaleType) {
          final newFormat = intl.DateFormat('dd/MM');
          return newFormat.format(value);
        },
        series: [
          BezierLine(
            label: "Duty",
            onMissingValue: (dateTime) {
              if (dateTime.day.isEven) {
                return 10.0;
              }
              return 5.0;
            },
            data: [
              DataPoint<DateTime>(value: 10, xAxis: date1),
              DataPoint<DateTime>(value: 50, xAxis: date2),
            ],
          ),
        ],
        config: BezierChartConfig(
          displayDataPointWhenNoValue: false,
          verticalIndicatorStrokeWidth: 3.0,
          pinchZoom: true,
          physics: ClampingScrollPhysics(),
          verticalIndicatorColor: Colors.black26,
          showVerticalIndicator: true,
          verticalIndicatorFixedPosition: false,
          backgroundColor: Colors.red,
        ),
      ),
    ),
  );
}

//SAMPLE DATE - MONTHLY

Widget sample4(BuildContext context) {
  final fromDate = DateTime(2018, 11, 22);
  final toDate = DateTime.now();

  final date1 = DateTime.now().subtract(Duration(days: 2));
  final date2 = DateTime.now().subtract(Duration(days: 3));

  final date3 = DateTime.now().subtract(Duration(days: 35));
  final date4 = DateTime.now().subtract(Duration(days: 36));

  final date5 = DateTime.now().subtract(Duration(days: 65));
  final date6 = DateTime.now().subtract(Duration(days: 64));

  return Center(
    child: Container(
      color: Colors.red,
      height: MediaQuery.of(context).size.height / 2,
      width: MediaQuery.of(context).size.width,
      child: BezierChart(
        bezierChartScale: BezierChartScale.MONTHLY,
        fromDate: fromDate,
        toDate: toDate,
        selectedDate: toDate,
        series: [
          BezierLine(
            label: "Duty",
            onMissingValue: (dateTime) {
              if (dateTime.month.isEven) {
                return 10.0;
              }
              return 5.0;
            },
            data: [
              DataPoint<DateTime>(value: 10, xAxis: date1),
              DataPoint<DateTime>(value: 50, xAxis: date2),
              DataPoint<DateTime>(value: 20, xAxis: date3),
              DataPoint<DateTime>(value: 80, xAxis: date4),
              DataPoint<DateTime>(value: 14, xAxis: date5),
              DataPoint<DateTime>(value: 30, xAxis: date6),
            ],
          ),
        ],
        config: BezierChartConfig(
          verticalIndicatorStrokeWidth: 3.0,
          verticalIndicatorColor: Colors.black26,
          showVerticalIndicator: true,
          verticalIndicatorFixedPosition: false,
          backgroundColor: Colors.red,
          footerHeight: 35.0,
        ),
      ),
    ),
  );
}

//SAMPLE DATE - YEARLY

Widget sample5(BuildContext context) {
  final fromDate = DateTime(2012, 11, 22);
  final toDate = DateTime.now();

  final date1 = DateTime.now().subtract(Duration(days: 2));
  final date2 = DateTime.now().subtract(Duration(days: 3));

  final date3 = DateTime.now().subtract(Duration(days: 300));
  final date4 = DateTime.now().subtract(Duration(days: 320));

  final date5 = DateTime.now().subtract(Duration(days: 650));
  final date6 = DateTime.now().subtract(Duration(days: 652));

  return Center(
    child: Container(
      color: Colors.red,
      height: MediaQuery.of(context).size.height / 2,
      width: MediaQuery.of(context).size.width,
      child: BezierChart(
        bezierChartScale: BezierChartScale.YEARLY,
        fromDate: fromDate,
        toDate: toDate,
        selectedDate: toDate,
        series: [
          BezierLine(
            label: "Duty",
            onMissingValue: (dateTime) {
              if (dateTime.year.isEven) {
                return 20.0;
              }
              return 5.0;
            },
            data: [
              DataPoint<DateTime>(value: 10, xAxis: date1),
              DataPoint<DateTime>(value: 50, xAxis: date2),
              DataPoint<DateTime>(value: 100, xAxis: date3),
              DataPoint<DateTime>(value: 100, xAxis: date4),
              DataPoint<DateTime>(value: 40, xAxis: date5),
              DataPoint<DateTime>(value: 47, xAxis: date6),
            ],
          ),
          BezierLine(
            label: "Flight",
            lineColor: Colors.black26,
            onMissingValue: (dateTime) {
              if (dateTime.month.isEven) {
                return 10.0;
              }
              return 3.0;
            },
            data: [
              DataPoint<DateTime>(value: 20, xAxis: date1),
              DataPoint<DateTime>(value: 30, xAxis: date2),
              DataPoint<DateTime>(value: 150, xAxis: date3),
              DataPoint<DateTime>(value: 80, xAxis: date4),
              DataPoint<DateTime>(value: 45, xAxis: date5),
              DataPoint<DateTime>(value: 45, xAxis: date6),
            ],
          ),
        ],
        config: BezierChartConfig(
          verticalIndicatorStrokeWidth: 3.0,
          verticalIndicatorColor: Colors.black26,
          showVerticalIndicator: true,
          verticalIndicatorFixedPosition: false,
          backgroundGradient: LinearGradient(
            colors: [
              Colors.red[300],
              Colors.red[400],
              Colors.red[400],
              Colors.red[500],
              Colors.red,
            ],
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
          ),
          footerHeight: 35.0,
        ),
      ),
    ),
  );
}

//MAIN SAMPLE
Widget sample6(BuildContext context) {
  return Container(
    decoration: BoxDecoration(
      gradient: LinearGradient(
        begin: Alignment.topCenter,
        end: Alignment.bottomCenter,
        colors: [
          Colors.black54,
          Colors.black87,
          Colors.black87,
        ],
      ),
    ),
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          "Bezier Chart",
          style: TextStyle(
            color: Colors.white,
            fontSize: 30,
            fontWeight: FontWeight.w500,
          ),
        ),
        _buildChart(
          BezierChartScale.MONTHLY,
          context,
          LinearGradient(
            colors: [
              Colors.red[300],
              Colors.red[400],
              Colors.red[400],
              Colors.red[500],
              Colors.red,
            ],
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
          ),
        ),
        _buildChart(
            BezierChartScale.YEARLY,
            context,
            LinearGradient(
              colors: [
                Colors.purple[300],
                Colors.purple[400],
                Colors.purple[400],
                Colors.purple[500],
                Colors.purple,
              ],
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
            ))
      ],
    ),
  );
}

_buildChart(
    BezierChartScale scale, BuildContext context, LinearGradient gradient) {
  final fromDate = DateTime(2012, 11, 22);
  final toDate = DateTime.now();

  final date1 = DateTime.now().subtract(Duration(days: 2));
  final date2 = DateTime.now().subtract(Duration(days: 3));

  final date3 = DateTime.now().subtract(Duration(days: 300));
  final date4 = DateTime.now().subtract(Duration(days: 320));

  final date5 = DateTime.now().subtract(Duration(days: 650));
  final date6 = DateTime.now().subtract(Duration(days: 652));

  return Center(
    child: Card(
      elevation: 10,
      margin: EdgeInsets.all(25.0),
      child: Container(
        color: Colors.red,
        height: MediaQuery.of(context).size.height / 3,
        width: MediaQuery.of(context).size.width,
        child: BezierChart(
          bezierChartScale: scale,
          fromDate: fromDate,
          toDate: toDate,
          selectedDate: toDate,
          series: [
            BezierLine(
              label: "Duty",
              onMissingValue: (dateTime) {
                if (dateTime.year.isEven) {
                  return 20.0;
                }
                return 5.0;
              },
              data: [
                DataPoint<DateTime>(value: 10, xAxis: date1),
                DataPoint<DateTime>(value: 50, xAxis: date2),
                DataPoint<DateTime>(value: 100, xAxis: date3),
                DataPoint<DateTime>(value: 100, xAxis: date4),
                DataPoint<DateTime>(value: 40, xAxis: date5),
                DataPoint<DateTime>(value: 47, xAxis: date6),
              ],
            ),
            BezierLine(
              label: "Flight",
              lineColor: Colors.black26,
              onMissingValue: (dateTime) {
                if (dateTime.month.isEven) {
                  return 10.0;
                }
                return 3.0;
              },
              data: [
                DataPoint<DateTime>(value: 20, xAxis: date1),
                DataPoint<DateTime>(value: 30, xAxis: date2),
                DataPoint<DateTime>(value: 150, xAxis: date3),
                DataPoint<DateTime>(value: 80, xAxis: date4),
                DataPoint<DateTime>(value: 45, xAxis: date5),
                DataPoint<DateTime>(value: 45, xAxis: date6),
              ],
            ),
          ],
          config: BezierChartConfig(
            verticalIndicatorStrokeWidth: 3.0,
            verticalIndicatorColor: Colors.black26,
            showVerticalIndicator: true,
            verticalIndicatorFixedPosition: false,
            backgroundGradient: gradient,
            footerHeight: 35.0,
          ),
        ),
      ),
    ),
  );
}

Widget sample7(BuildContext context) {
  return Container(
    decoration: BoxDecoration(
      gradient: LinearGradient(
        colors: [
          Colors.black54,
          Colors.black87,
          Colors.black87,
          Colors.black,
        ],
        begin: Alignment.topCenter,
        end: Alignment.bottomCenter,
      ),
    ),
    child: Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Text(
          "Bezier Chart - Numbers",
          style: TextStyle(
            color: Colors.white,
            fontSize: 28,
            fontWeight: FontWeight.w700,
          ),
        ),
        Center(
          child: Card(
            elevation: 12,
            child: Container(
              height: MediaQuery.of(context).size.height / 2,
              width: MediaQuery.of(context).size.width * 0.9,
              child: BezierChart(
                bezierChartScale: BezierChartScale.CUSTOM,
                xAxisCustomValues: const [0, 5, 10, 15, 20, 25, 30, 35],
                footerValueBuilder: (double value) {
                  return "${formatAsIntOrDouble(value)}\ndays";
                },
                series: const [
                  BezierLine(
                    label: "m",
                    data: const [
                      DataPoint<double>(value: 100, xAxis: 0),
                      DataPoint<double>(value: 130, xAxis: 5),
                      DataPoint<double>(value: 300, xAxis: 10),
                      DataPoint<double>(value: 150, xAxis: 15),
                      DataPoint<double>(value: 75, xAxis: 20),
                      DataPoint<double>(value: 100, xAxis: 25),
                      DataPoint<double>(value: 250, xAxis: 30),
                      DataPoint<double>(value: 120, xAxis: 35),
                    ],
                  ),
                ],
                config: BezierChartConfig(
                  displayLinesXAxis: true,
                  startYAxisFromNonZeroValue: true,
                  bubbleIndicatorColor: Colors.white.withOpacity(0.9),
                  footerHeight: 40,
                  displayYAxis: true,
                  stepsYAxis: 15,
                  backgroundGradient: LinearGradient(
                    colors: [
                      Colors.red[300],
                      Colors.red[400],
                      Colors.red[400],
                      Colors.red[500],
                      Colors.red,
                    ],
                    begin: Alignment.topCenter,
                    end: Alignment.bottomCenter,
                  ),
                  snap: false,
                ),
              ),
            ),
          ),
        ),
      ],
    ),
  );
}

//SAMPLE 8 Hourly Chart
Widget sample8(BuildContext context) {
  final fromDate = DateTime.now().subtract(Duration(hours: 50));
  final toDate = DateTime.now();

  final date1 = toDate.subtract(Duration(hours: 2));
  final date2 = toDate.subtract(Duration(hours: 3));

  final date3 = toDate.subtract(Duration(hours: 10));
  final date4 = toDate.subtract(Duration(hours: 15));

  final date5 = toDate.subtract(Duration(hours: 19));
  final date6 = toDate.subtract(Duration(hours: 26));

  return Center(
    child: Container(
      color: Colors.red,
      height: MediaQuery.of(context).size.height / 2,
      width: MediaQuery.of(context).size.width,
      child: BezierChart(
        bezierChartScale: BezierChartScale.HOURLY,
        fromDate: fromDate,
        toDate: toDate,
        selectedDate: toDate,
        series: [
          BezierLine(
            label: "Duty",
            data: [
              DataPoint<DateTime>(value: 0, xAxis: date1),
              DataPoint<DateTime>(value: 50, xAxis: date2),
              DataPoint<DateTime>(value: 100, xAxis: date3),
              DataPoint<DateTime>(value: 100, xAxis: date4),
              DataPoint<DateTime>(value: 40, xAxis: date5),
              DataPoint<DateTime>(value: 47, xAxis: date6),
            ],
          ),
        ],
        config: BezierChartConfig(
          verticalIndicatorStrokeWidth: 3.0,
          verticalIndicatorColor: Colors.black26,
          showVerticalIndicator: true,
          verticalIndicatorFixedPosition: false,
          bubbleIndicatorTitleStyle: TextStyle(
            color: Colors.blue,
          ),
          bubbleIndicatorLabelStyle: TextStyle(
            color: Colors.red,
          ),
          displayYAxis: true,
          stepsYAxis: 25,
          backgroundGradient: LinearGradient(
            colors: [
              Colors.red[300],
              Colors.red[400],
              Colors.red[400],
              Colors.red[500],
              Colors.red,
            ],
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
          ),
          footerHeight: 35.0,
        ),
      ),
    ),
  );
}

//Example of the problem with BezierChartScale.WEEKLY
Widget sample9(BuildContext context) {
  int dateInt1 = 1562013034796;
  int dateInt2 = 1562079398067;
  final fromDate = DateTime.fromMillisecondsSinceEpoch(dateInt1);
  final toDate = DateTime.fromMillisecondsSinceEpoch(dateInt2);
  final DateTime date1 = DateTime.fromMillisecondsSinceEpoch(dateInt1);
  final DateTime date2 = DateTime.fromMillisecondsSinceEpoch(dateInt2);
  //final date1 = DateTime.now().subtract(Duration(days: 2));
  //final date2 = DateTime.now().subtract(Duration(days: 3));
  return Center(
    child: Container(
      color: Colors.red,
      height: MediaQuery.of(context).size.height / 2,
      width: MediaQuery.of(context).size.width,
      child: BezierChart(
        fromDate: fromDate,
        bezierChartScale: BezierChartScale.WEEKLY,
        toDate: toDate,
        onIndicatorVisible: (val) {
          print("Indicator Visible :$val");
        },
        onDateTimeSelected: (datetime) {
          print("selected datetime: $datetime");
        },
        selectedDate: toDate,
        //this is optional
        footerDateTimeBuilder: (DateTime value, BezierChartScale scaleType) {
          final newFormat = intl.DateFormat('dd/MM');
          return newFormat.format(value);
        },
        series: [
          BezierLine(
            label: "Duty",
            /*  onMissingValue: (dateTime) {
              if (dateTime.day.isEven) {
                return 10.0;
              }
              return 5.0;
            },*/
            data: [
              DataPoint<DateTime>(value: 10, xAxis: date1),
              DataPoint<DateTime>(value: 50, xAxis: date2),
            ],
          ),
        ],
        config: BezierChartConfig(
          verticalIndicatorStrokeWidth: 3.0,
          pinchZoom: false,
          verticalIndicatorColor: Colors.black26,
          showVerticalIndicator: true,
          verticalIndicatorFixedPosition: false,
          backgroundColor: Colors.red,
        ),
      ),
    ),
  );
}

// bubbleLabelDateTimeBuilder usage example
Widget sample11(BuildContext context) {
  final fromDate = DateTime(2019, 05, 22);
  final toDate = DateTime.now();
  final date1 = DateTime.now().subtract(Duration(days: 2));
  final date2 = DateTime.now().subtract(Duration(days: 3));
  return Center(
    child: Container(
      color: Colors.red,
      //height: MediaQuery.of(context).size.height / 2,
      //width: MediaQuery.of(context).size.width,
      child: BezierChart(
        fromDate: fromDate,
        bezierChartScale: BezierChartScale.WEEKLY,
        toDate: toDate,
        onIndicatorVisible: (val) {
          print("Indicator Visible :$val");
        },
        onDateTimeSelected: (datetime) {
          print("selected datetime: $datetime");
        },
        selectedDate: toDate,
        //this is optional
        footerDateTimeBuilder: (DateTime value, BezierChartScale scaleType) {
          final newFormat = intl.DateFormat('dd/MMM');
          return newFormat.format(value);
        },
        bubbleLabelDateTimeBuilder:
            (DateTime value, BezierChartScale scaleType) {
          final newFormat = intl.DateFormat('EEE d');
          return "${newFormat.format(value)}\n";
        },
        series: [
          BezierLine(
            label: "Duty",
            onMissingValue: (dateTime) {
              if (dateTime.day.isEven) {
                return 10.0;
              }
              return 5.0;
            },
            data: [
              DataPoint<DateTime>(value: 30, xAxis: fromDate),
              DataPoint<DateTime>(value: 20, xAxis: date1),
              DataPoint<DateTime>(value: 50, xAxis: date2),
            ],
          ),
        ],
        config: BezierChartConfig(
          displayDataPointWhenNoValue: false,
          verticalIndicatorStrokeWidth: 3.0,
          pinchZoom: false,
          verticalIndicatorColor: Colors.black26,
          showVerticalIndicator: true,
          verticalIndicatorFixedPosition: false,
          backgroundColor: Colors.red,
        ),
      ),
    ),
  );
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  bezier_chart: ^1.0.17+1

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:bezier_chart/bezier_chart.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
92
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
96
Learn more about scoring.

We analyzed this package on Jul 2, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.13
  • Flutter: 1.17.5

Analysis suggestions

Package not compatible with SDK dart

because of import path [bezier_chart] that is in a package requiring null.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
intl ^0.16.0 0.16.1
Transitive dependencies
collection 1.14.12 1.14.13
meta 1.1.8
path 1.7.0
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8
Dev dependencies
flutter_test