Giter Site home page Giter Site logo

flutter_circular_chart's Introduction

pub package

Flutter Circular Chart

A library for creating animated circular chart widgets with Flutter, inspired by Zero to One with Flutter.

Overview

Create easily animated pie charts and radial charts by providing them with data objects they can plot into charts and animate between.

animated_random_radial_chart

animated pie chart animated radial chart

Check the examples folder for the source code for the above screenshots.

Contents:

Installation

Install the latest version from pub.

Getting Started

Import the package:

import 'package:flutter_circular_chart/flutter_circular_chart.dart';

Create a GlobalKey to be able to access the chart and update its data:

final GlobalKey<AnimatedCircularChartState> _chartKey = new GlobalKey<AnimatedCircularChartState>();

Create chart data entry objects:

List<CircularStackEntry> data = <CircularStackEntry>[
  new CircularStackEntry(
    <CircularSegmentEntry>[
      new CircularSegmentEntry(500.0, Colors.red[200], rankKey: 'Q1'),
      new CircularSegmentEntry(1000.0, Colors.green[200], rankKey: 'Q2'),
      new CircularSegmentEntry(2000.0, Colors.blue[200], rankKey: 'Q3'),
      new CircularSegmentEntry(1000.0, Colors.yellow[200], rankKey: 'Q4'),
    ],
    rankKey: 'Quarterly Profits',
  ),
];

Create an AnimatedCircularChart, passing it the _chartKey and initial data:

@override
Widget build(BuildContext context) {
  return new AnimatedCircularChart(
    key: _chartKey,
    size: const Size(300.0, 300.0),
    initialChartData: data,
    chartType: CircularChartType.Pie,
  );
}

Call updateData to animate the chart:

void _cycleSamples() {
  List<CircularStackEntry> nextData = <CircularStackEntry>[
    new CircularStackEntry(
      <CircularSegmentEntry>[
        new CircularSegmentEntry(1500.0, Colors.red[200], rankKey: 'Q1'),
        new CircularSegmentEntry(750.0, Colors.green[200], rankKey: 'Q2'),
        new CircularSegmentEntry(2000.0, Colors.blue[200], rankKey: 'Q3'),
        new CircularSegmentEntry(1000.0, Colors.yellow[200], rankKey: 'Q4'),
      ],
      rankKey: 'Quarterly Profits',
    ),
  ];
  setState(() {
    _chartKey.currentState.updateData(nextData);
  });
}

Customization

Hole Label:

Property Default
holeLabel null
labelStyle Theme.of(context).textTheme.body2

Example:

new AnimatedCircularChart(
  key: _chartKey,
  size: _chartSize,
  initialChartData: <CircularStackEntry>[
    new CircularStackEntry(
      <CircularSegmentEntry>[
        new CircularSegmentEntry(
          33.33,
          Colors.blue[400],
          rankKey: 'completed',
        ),
        new CircularSegmentEntry(
          66.67,
          Colors.blueGrey[600],
          rankKey: 'remaining',
        ),
      ],
      rankKey: 'progress',
    ),
  ],
  chartType: CircularChartType.Radial,
  percentageValues: true,
  holeLabel: '1/3',
  labelStyle: new TextStyle(
    color: Colors.blueGrey[600],
    fontWeight: FontWeight.bold,
    fontSize: 24.0,
  ),
)

hole label example screenshot


Segment Edge Style:

Property Default
edgeStyle SegmentEdgeStyle.flat
SegmentEdgeStyle Description
flat (default) Segments begin and end with a flat edge.
round Segments begin and end with a semi-circle.

Example:

new AnimatedCircularChart(
  key: _chartKey,
  size: _chartSize,
  initialChartData: <CircularStackEntry>[
    new CircularStackEntry(
      <CircularSegmentEntry>[
        new CircularSegmentEntry(
          33.33,
          Colors.blue[400],
          rankKey: 'completed',
        ),
        new CircularSegmentEntry(
          66.67,
          Colors.blueGrey[600],
          rankKey: 'remaining',
        ),
      ],
      rankKey: 'progress',
    ),
  ],
  chartType: CircularChartType.Radial,
  edgeStyle: SegmentEdgeStyle.round,
  percentageValues: true,
)

round segment edge example screenshot

Details

Chart data entries:

Charts expect a list of CircularStackEntry objects containing the data they need to be drawn.

Each CircularStackEntry corresponds to a complete circle in the chart. For radial charts that is one of the rings, for pie charts it is the whole pie.

Radial charts with multiple CircularStackEntrys will display them as concentric circles.

Each CircularStackEntry is composed of multiple CircularSegmentEntrys containing the value of a data point. In radial charts a segment corresponds to an arc segment of the current ring, for pie charts it is an individual slice.

flutter_circular_chart's People

Contributors

rkc13 avatar xqwzts avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flutter_circular_chart's Issues

Issue when in a listview

Basically, the circular charts were fine when they were in a static widget. But when I put them in a statefull widget (listview), and scrolled (triggering a redraw) crazy stuff started happening. One of the segments turned straight, and the whole widget just started flickering.

here's my code

import 'dart:math';
import 'package:moves/screencomponents/my_flutter_app_icons.dart';
import 'package:flutter/material.dart';
import 'package:flutter_sparkline/flutter_sparkline.dart';
import 'package:flutter_circular_chart/flutter_circular_chart.dart';
import 'browse/browse.dart';


class StockDetails extends StatefulWidget {
  @override
  _StockDetailsState createState() => _StockDetailsState();
}

class _StockDetailsState extends State<StockDetails> {
  final GlobalKey<AnimatedCircularChartState> _chartKey1 =
      GlobalKey<AnimatedCircularChartState>();

  final GlobalKey<AnimatedCircularChartState> _chartKey2 =
      GlobalKey<AnimatedCircularChartState>();

  List<double> mockData = [1.0, 6.0, 4.0, 3.0, 8.0, 6.0, 4.0, 6.0, 3.0];

  List<CircularStackEntry> data1 = <CircularStackEntry>[
    CircularStackEntry(
      <CircularSegmentEntry>[
        CircularSegmentEntry(22.0, Colors.red[200], rankKey: 'Q1'),
        CircularSegmentEntry(88.0, Colors.grey[300], rankKey: 'Q2'),
      ],
      rankKey: 'Quarterly Profits1',
    ),
  ];

  List<CircularStackEntry> data2 = <CircularStackEntry>[
    CircularStackEntry(
      <CircularSegmentEntry>[
        CircularSegmentEntry(22.0, Colors.green[200], rankKey: 'Q3'),
        CircularSegmentEntry(88.0, Colors.grey[300], rankKey: 'Q4'),
      ],
      rankKey: 'Quarterly Profits2',
    ),
  ];

  TextStyle titleTextStyle() {
    return TextStyle(
      fontSize: 19.0,
      fontWeight: FontWeight.w500,
      letterSpacing: 1.5,
      color: Colors.black,
      wordSpacing: 0.5,
    );
  }

  TextStyle middleTextStyle() {
    return TextStyle(
      fontSize: 14.5,
      fontWeight: FontWeight.w400,
      letterSpacing: 1.0,
      color: Colors.black,
      wordSpacing: 0.5,
    );
  }

  Widget timePeriod(String timeInterval) {
    return Padding(
      padding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0),
      child: Container(
        decoration: BoxDecoration(
            shape: BoxShape.rectangle,
            color: Colors.white,
            borderRadius: BorderRadius.circular(15.0),
            border: Border.all()),
        height: 20.0,
        width: 35.0,
        child: Center(
          child: Text(
            timeInterval,
            style: middleTextStyle(),
          ),
        ),
      ),
    );
  }

  Widget infoCard() {
    return Padding(
        padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.0364,
            0.0, MediaQuery.of(context).size.width * 0.0364, 0.0),
        child: Card(
          elevation: 10.0,
          child: Container(
            height: MediaQuery.of(context).size.width * 0.1458,
            width: double.infinity,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                Expanded(
                  child: Padding(
                    padding: EdgeInsets.fromLTRB(
                        MediaQuery.of(context).size.width * 0.024,
                        MediaQuery.of(context).size.height * 0.00645,
                        0.0,
                        0.0),
                    child: Column(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(
                          "3.1M Bet Against Apple Inc.",
                          style: titleTextStyle(),
                        ),
                        Text(
                          "12/4/2018 04:00PM",
                          style: middleTextStyle(),
                        ),
                      ],
                    ),
                  ),
                ),
                Container(
                  color: Colors.transparent,
                  height: MediaQuery.of(context).size.height * .0774,
                  width: MediaQuery.of(context).size.width * .12153,
                  alignment: Alignment(
                      0.0, MediaQuery.of(context).size.height * -0.00451),
                  child: IconButton(
                    icon: Icon(Icons.bookmark),
                    color: Colors.black,
                    onPressed: () {
                      print(MediaQuery.of(context).size.width);
                    },
                  ),
                ),
              ],
            ),
          ),
        ));
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        decoration: BoxDecoration(
            gradient: LinearGradient(
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
                colors: [const Color(0xFFffffff), const Color(0xFFdfe9f3)])),
        child: Scaffold(
          backgroundColor: Colors.transparent,
          appBar: AppBar(
            centerTitle: true,
            backgroundColor: Colors.transparent,
            elevation: 0.0,
            title: Padding(
              padding: EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0),
              child: Column(
                children: <Widget>[
                  Text(
                    "Apple Inc.",
                    style: titleTextStyle(),
                  ),
                  Text(
                    "NYSE - APPL",
                    style: middleTextStyle(),
                  )
                ],
              ),
            ),
            leading: IconButton(
              onPressed: () {
                print("leading pressed");
              },
              icon: Icon(
                Icons.arrow_back,
                color: Colors.black,
              ),
            ),
            actions: <Widget>[
              IconButton(
                icon: Icon(Icons.remove_red_eye),
                color: Colors.black,
                onPressed: () {
                  print("watch pressed!");
                },
              )
            ],
          ),
          body: ListView(
            children: <Widget>[
              Padding(
                padding: EdgeInsets.fromLTRB(
                    MediaQuery.of(context).size.width * 0.11,
                    MediaQuery.of(context).size.height * .038,
                    MediaQuery.of(context).size.width * 0.11,
                    0.0),
                child: Container(
                  height: MediaQuery.of(context).size.height * 0.257,
                  width: double.infinity,
                  decoration:
                      BoxDecoration(border: Border.all(), color: Colors.white),
                  child: Stack(
                    children: <Widget>[
                      Padding(
                        padding: EdgeInsets.fromLTRB(0.0, 50.0, 0.0, 0.0),
                        child: Sparkline(
                          lineColor: Colors.black,
                          data: mockData,
                          fillMode: FillMode.below,
                          fillGradient: new LinearGradient(
                            begin: Alignment(0.0, -1.4),
                            end: Alignment(0.0, 1.0),
                            colors: [Colors.green, Colors.white],
                          ),
                        ),
                      ),
                      Padding(
                        padding: EdgeInsets.fromLTRB(10.0, 10.0, 0.0, 0.0),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.start,
                          children: <Widget>[
                            Text(
                              r"$120.53",
                              style: TextStyle(
                                  fontSize: 35.0,
                                  fontWeight: FontWeight.w600,
                                  letterSpacing: 1.5,
                                  color: Colors.black,
                                  wordSpacing: 0.5),
                            ),
                            Padding(
                              padding: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0),
                              child: Icon(
                                MyFlutterApp.asset_1,
                                color: Colors.green,
                                size: 14.0,
                              ),
                            ),
                            Padding(
                              padding:
                                  EdgeInsets.fromLTRB(15.0, 15.0, 0.0, 0.0),
                              child: Text(
                                "0.09%",
                                style: middleTextStyle(),
                              ),
                            ),
                          ],
                        ),
                      ),
                      Container(
                        alignment: Alignment(0.0, 1.1),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.end,
                          children: <Widget>[
                            Padding(
                              padding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
                              child: Text(
                                "more info",
                                style: middleTextStyle(),
                              ),
                            ),
                            IconButton(
                              //TODO: render inkwell ontop.
                              icon: Icon(Icons.keyboard_arrow_down),
                              onPressed: () {
                                print("More info pressed");
                                //todo: i'm going to basically turn this container into an expanded box. reference lib/screencomponents/expandedcard.dart
                              },
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  timePeriod("1D"),
                  timePeriod("1W"),
                  timePeriod("1M"),
                  timePeriod("3M"),
                  timePeriod("1Y"),
                  timePeriod("5Y"),
                ],
              ),
              Padding(
                padding: EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Column(
                      children: <Widget>[
                        Text("% short"),
                        AnimatedCircularChart(
                          holeRadius: 30.0,
                          key: _chartKey1,
                          size: Size(150.0, 150.0),
                          initialChartData: data1,
                          chartType: CircularChartType.Radial,
                          edgeStyle: SegmentEdgeStyle.flat,
                        ),
                      ],
                    ),
                    Column(
                      children: <Widget>[
                        Text("% for"),
                        AnimatedCircularChart(
                          holeRadius: 30.0,
                          key: _chartKey2,
                          size: Size(150.0, 150.0),
                          initialChartData: data2,
                          chartType: CircularChartType.Radial,
                          edgeStyle: SegmentEdgeStyle.flat,
                        ),
                      ],
                    ),
                  ],
                ),
              ), //row
              Column(
                children: <Widget>[
                  Text("Strange Trades"),
                ],
              ),
            ],
          ),
        ));
  }
}

weirdbug

Cannot customize radial chart stroke width

There are no params for that. And all I do for now it hard code the stroke width...

void _paintChart(Canvas canvas, Size size, CircularChart chart) {
  final Paint segmentPaint = new Paint()
    ..style = chart.chartType == CircularChartType.Radial
        ? PaintingStyle.stroke
        : PaintingStyle.fill
    ..strokeCap = chart.edgeStyle == SegmentEdgeStyle.round
        ? StrokeCap.round
        : StrokeCap.butt;

  for (final CircularChartStack stack in chart.stacks) {
    for (final segment in stack.segments) {
      segmentPaint.color = segment.color;
      segmentPaint.strokeWidth = 3;//stack.width;

      canvas.drawArc(
        new Rect.fromCircle(
          center: new Offset(size.width / 2, size.height / 2),
          radius: stack.radius,
        ),
        stack.startAngle * _kRadiansPerDegree,
        segment.sweepAngle * _kRadiansPerDegree,
        chart.chartType == CircularChartType.Pie,
        segmentPaint,
      );
    }
  }
}

Does not work with Flutter 0.6.0

When upgrading the library to flutter 0.6.0, the library fails to solve versions:

The current Dart SDK version is 2.1.0-dev.0.0.flutter-be6309690f.

Because flutter_circular_chart 0.0.3 requires SDK version >=1.19.0 <2.0.0 and no versions of flutter_circular_chart match >0.0.3 <0.1.0, flutter_circular_chart ^0.0.3 is forbidden.
So, because flutter_example depends on flutter_circular_chart ^0.0.3, version solving failed.
pub get failed (1)

Improve README

  • Overview
  • Installation
  • Getting started
  • Creating data with CircularSegmentEntry and CircularStackEntry
  • Displaying a static chart with CircularChart
  • Animating charts with AnimatedCircularChart
  • Explain rankKey
  • Screenshots
  • Contributing

How to create GlobalKey?

I have no idea how to create final GlobalKey _chartKey; It is not clearly mentioned in the document. I am new to Dart + Flutter

Without even passing this object my chart is rendered properly. What am I missing then?

Version 1.0.0 is not compatible with flutter 3.22.0.

I'm compiling my project with the latest flutter version 3.22.0.

I got the following compile error:

../../.pub-cache/hosted/pub.dev/awesome_circular_chart-1.0.0/lib/src/animated_circular_chart.dart:221:60: Error: The getter 'bodyText1' isn't defined for the class 'TextTheme'.
 - 'TextTheme' is from 'package:flutter/src/material/text_theme.dart' ('../../Documents/workspace/flutter/packages/flutter/lib/src/material/text_theme.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named 'bodyText1'.
          widget.labelStyle ?? Theme.of(context).textTheme.bodyText1;
                                                           ^^^^^^^^^
Target kernel_snapshot failed: Exception


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileFlutterBuildRelease'.
> Process 'command '/workspace/flutter/bin/flutter'' finished with non-zero exit value 1

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 8s

Is this a known issue?

Document public APIs

All public APIs need proper documentation:

  • AnimatedCircularChart
  • CircularChart
  • CircularChartTween
  • CircularSegmentEntry
  • CircularStackEntry

Issue since FLUTTER 2.0 upgrade

Filename:
.../AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/flutter_circular_chart-0.1.0/lib/src/animated_circular_chart.dart

The below line is giving error while building app:
line 121, 122:
final AnimatedCircularChartState result = context
.ancestorStateOfType(const TypeMatcher());

ERROR:
_The method 'ancestorStateOfType' isn't defined for the class 'BuildContext'.

  • 'BuildContext' is from 'package:flutter/src/widgets/framework.dart' ('/C:/flutter/packages/flutter/lib/src/widgets/framework.dart').
    Try correcting the name to the name of an existing method, or defining a method named 'ancestorStateOfType'.
    context.ancestorStateOfType(const TypeMatcher());

FAILURE: Build failed with an exception.

  • Where:
    Script 'C:\flutter\packages\flutter_tools\gradle\flutter.gradle' line: 991

  • What went wrong:
    Execution failed for task ':app:compileFlutterBuildDebug'.

Process 'command 'C:\flutter\bin\flutter.bat'' finished with non-zero exit value 1

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

  • Get more help at https://help.gradle.org

BUILD FAILED in 20s
Running Gradle task 'assembleDebug'...
Running Gradle task 'assembleDebug'... Done 21.9s
Exception: Gradle task assembleDebug failed with exit code 1_

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.