A library for creating animated circular chart widgets with Flutter.
Create easily animated pie charts and radial charts by providing them with data objects they can plot into charts and animate between.
Step 1: Install it
Run this command:
With Flutter:
$ flutter pub add flutter_circular_chart
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
flutter_circular_chart: ^0.1.0
Alternatively, your editor might support flutter pub get
. Check the docs for your editor to learn more.
Step 2: 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>();
Step 3: Create Charts
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,
),
)
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,
)
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 CircularStackEntry
s will display them as concentric circles.
Each CircularStackEntry
is composed of multiple CircularSegmentEntry
s 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.
Full Examples
Here are some examples of using this plugin to create circular charts. Let us start by creating a color pallete:
color_palette.dart
import 'dart:math';
import 'package:flutter/material.dart';
class ColorPalette {
static final ColorPalette primary = new ColorPalette(<Color>[
Colors.blue[400],
Colors.blue[200],
Colors.red[400],
Colors.red[200],
Colors.green[400],
Colors.green[200],
Colors.yellow[400],
Colors.yellow[200],
Colors.purple[400],
Colors.purple[200],
Colors.orange[400],
Colors.orange[200],
Colors.teal[400],
Colors.teal[200],
Colors.black,
]);
ColorPalette(List<Color> colors) : _colors = colors {
assert(colors.isNotEmpty);
}
final List<Color> _colors;
Color operator [](int index) => _colors[index % length];
int get length => _colors.length;
Color random(Random random) => this;
}
1. Animated Pie Chart
Here is an example of animated piechart:
animated_pie_chart_example.dart.dart
import 'package:flutter/material.dart';
import 'package:flutter_circular_chart/flutter_circular_chart.dart';
void main() {
runApp(new MaterialApp(
home: new AnimatedPieChartExample(),
));
}
final List<List<CircularStackEntry>> _quarterlyProfitPieData = [
<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',
),
],
<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',
),
],
<CircularStackEntry>[
new CircularStackEntry(
<CircularSegmentEntry>[
new CircularSegmentEntry(1800.0, Colors.red[200], rankKey: 'Q1'),
new CircularSegmentEntry(2900.0, Colors.green[200], rankKey: 'Q2'),
new CircularSegmentEntry(4000.0, Colors.blue[200], rankKey: 'Q3'),
new CircularSegmentEntry(7000.0, Colors.yellow[200], rankKey: 'Q4'),
],
rankKey: 'Quarterly Profits',
),
],
];
class AnimatedPieChartExample extends StatefulWidget {
@override
_AnimatedPieChartExampleState createState() =>
new _AnimatedPieChartExampleState();
}
class _AnimatedPieChartExampleState extends State<AnimatedPieChartExample> {
final GlobalKey<AnimatedCircularChartState> _chartKey =
new GlobalKey<AnimatedCircularChartState>();
final _chartSize = const Size(300.0, 300.0);
int sampleIndex = 0;
void _cycleSamples() {
setState(() {
sampleIndex++;
List<CircularStackEntry> data = _quarterlyProfitPieData[sampleIndex % 3];
_chartKey.currentState.updateData(data);
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: const Text('Quarterly Profit'),
),
body: new Center(
child: new AnimatedCircularChart(
key: _chartKey,
size: _chartSize,
initialChartData: _quarterlyProfitPieData[0],
chartType: CircularChartType.Pie,
),
),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.refresh),
onPressed: _cycleSamples,
),
);
}
}
2. Animated Radial Chart
animated_radial_chart_example.dart
import 'package:flutter/material.dart';
import 'package:flutter_circular_chart/flutter_circular_chart.dart';
void main() {
runApp(new MaterialApp(
home: new AnimatedRadialChartExample(),
));
}
class AnimatedRadialChartExample extends StatefulWidget {
@override
_AnimatedRadialChartExampleState createState() =>
new _AnimatedRadialChartExampleState();
}
class _AnimatedRadialChartExampleState
extends State<AnimatedRadialChartExample> {
final GlobalKey<AnimatedCircularChartState> _chartKey =
new GlobalKey<AnimatedCircularChartState>();
final _chartSize = const Size(200.0, 200.0);
double value = 50.0;
Color labelColor = Colors.blue[200];
void _increment() {
setState(() {
value += 10;
List<CircularStackEntry> data = _generateChartData(value);
_chartKey.currentState.updateData(data);
});
}
void _decrement() {
setState(() {
value -= 10;
List<CircularStackEntry> data = _generateChartData(value);
_chartKey.currentState.updateData(data);
});
}
List<CircularStackEntry> _generateChartData(double value) {
Color dialColor = Colors.blue[200];
if (value < 0) {
dialColor = Colors.red[200];
} else if (value < 50) {
dialColor = Colors.yellow[200];
}
labelColor = dialColor;
List<CircularStackEntry> data = <CircularStackEntry>[
new CircularStackEntry(
<CircularSegmentEntry>[
new CircularSegmentEntry(
value,
dialColor,
rankKey: 'percentage',
)
],
rankKey: 'percentage',
),
];
if (value > 100) {
labelColor = Colors.green[200];
data.add(new CircularStackEntry(
<CircularSegmentEntry>[
new CircularSegmentEntry(
value - 100,
Colors.green[200],
rankKey: 'percentage',
),
],
rankKey: 'percentage2',
));
}
return data;
}
@override
Widget build(BuildContext context) {
TextStyle _labelStyle = Theme
.of(context)
.textTheme
.title
.merge(new TextStyle(color: labelColor));
return new Scaffold(
appBar: new AppBar(
title: const Text('Percentage Dial'),
),
body: new Column(
children: <Widget>[
new Container(
child: new AnimatedCircularChart(
key: _chartKey,
size: _chartSize,
initialChartData: _generateChartData(value),
chartType: CircularChartType.Radial,
edgeStyle: SegmentEdgeStyle.round,
percentageValues: true,
holeLabel: '$value%',
labelStyle: _labelStyle,
),
),
new Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
new RaisedButton(
onPressed: _decrement,
child: const Icon(Icons.remove),
shape: const CircleBorder(),
color: Colors.red[200],
textColor: Colors.white,
),
new RaisedButton(
onPressed: _increment,
child: const Icon(Icons.add),
shape: const CircleBorder(),
color: Colors.blue[200],
textColor: Colors.white,
),
],
),
],
),
);
}
}
3. Animated Random Radial Chart
Here is an example of Animated Random Radial Chart:
animated_random_radial_chart_example.dart
import 'package:flutter/material.dart';
import 'package:flutter_circular_chart/flutter_circular_chart.dart';
import 'dart:math' as Math;
import 'color_palette.dart';
void main() {
runApp(new MaterialApp(
home: new RandomizedRadialChartExample(),
));
}
class RandomizedRadialChartExample extends StatefulWidget {
@override
_RandomizedRadialChartExampleState createState() =>
new _RandomizedRadialChartExampleState();
}
class _RandomizedRadialChartExampleState
extends State<RandomizedRadialChartExample> {
final GlobalKey<AnimatedCircularChartState> _chartKey =
new GlobalKey<AnimatedCircularChartState>();
final _chartSize = const Size(300.0, 300.0);
final Math.Random random = new Math.Random();
List<CircularStackEntry> data;
@override
void initState() {
super.initState();
data = _generateRandomData();
}
double value = 50.0;
void _randomize() {
setState(() {
data = _generateRandomData();
_chartKey.currentState.updateData(data);
});
}
List<CircularStackEntry> _generateRandomData() {
int stackCount = random.nextInt(10);
List<CircularStackEntry> data = new List.generate(stackCount, (i) {
int segCount = random.nextInt(10);
List<CircularSegmentEntry> segments = new List.generate(segCount, (j) {
Color randomColor = ColorPalette.primary.random(random);
return new CircularSegmentEntry(random.nextDouble(), randomColor);
});
return new CircularStackEntry(segments);
});
return data;
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: const Text('Randomized radial data'),
),
body: new Center(
child: new AnimatedCircularChart(
key: _chartKey,
size: _chartSize,
initialChartData: data,
chartType: CircularChartType.Radial,
),
),
floatingActionButton: new FloatingActionButton(
onPressed: _randomize,
child: const Icon(Icons.refresh),
),
);
}
}
Reference
Read more here.
Download code Here.
Follow code author here.