Customizable charts library for flutter.
Idea behind this lib is to allow highly customizable charts. By having decorations painters (foreground and background) and item painters that can be easily changed. Customizing and adding new decorations will require some CustomPainter knowledge.
Add it to your package's pubspec.yaml file
dependencies:
charts_painter: ^1.0.0
Install packages from the command line
flutter packages get
By passing ChartState.line
or ChartState.bar
to Chart widget we will add appropriate decorations for the selected chart.
@override
Widget build(BuildContext context) {
return Chart(
state: ChartState.line(
ChartData.fromList(
<double>[1, 3, 4, 2, 7, 6, 2, 5, 4].map((e) => BubbleValue<void>(e)).toList(),
),
),
);
}
By charging ChartState.line
to ChartState.bar
we can change look of the chart.
@override
Widget build(BuildContext context) {
return Chart(
state: ChartState.bar(
ChartData.fromList(
<double>[1, 3, 4, 2, 7, 6, 2, 5, 4].map((e) => BarValue<void>(e)).toList(),
),
),
);
}
Chart data has some options that will change how the data is processed.
By changing axisMin
or axisMax
scale of the chart is changed in order to show that value, in case data has higher/lower data than axisMax/axisMin, then this option is ignored.
Adding valueAxisMaxOver
will add that value to currently the highest value.
strategy
will only have impact if chart has multiple lists, in that case it can stack those items with DataStrategy.stack
. Strategy only affects how multiple lists are being processed, to change how the are drawn see ChartBehaviour.multiItemStack
Options that set how it draws each item and how it looks.
When using BarItemOptions
or BubbleItemOptions
geometry painters have been preset, and they include some extra options for their painters.
What are geometry painters?
Geometry painters are responsible for drawing each item on the canvas.
Included in the lib are 2 ItemPainter
's.
Bar painter (default) | Bubble painter |
---|---|
![]() |
![]() |
![]() |
We use Decorations to enhance our charts. Chart decorations can be painted in the background or in a foreground of the items. Everything that is not chart item is a decoration.
Here are decorations we have included, bar items with opacity have been added for better visibility.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
- GridDecoration - Decoration is just merging of HorizontalAxisDecoration and VerticalAxisDecoration
- HorizontalAxisDecoration - Show horizontal lines on the chart, can show legend as well
- VerticalAxisDecoration - Show vertical lines on the chart, can show legend as well
- ValueDecoration - Show value of each item
- TargetLineDecoration - Show target line on the chart, can pass
getTargetItemColor
tocolorForValue
to change item colors- TargetLineLegendDecoration - Show text legend on left side of the chart
- TargetAreaDecoration
- BorderDecoration - Add rectangular border around the chart
- SelectedItemDecoration - When providing
ChartBehaviour.onItemClicked
then you can useSelectedItemDecoration
for showing selected item on the chart - SparkLineDecoration - Show data with sparkline chart
Now you are ready to use charts lib. If chart needs to animate the state changes then use AnimatedChart<T>
widget instead of Chart<T>
widget.
AnimatedChart<T>
needs to specify Duration
and it can accept Curve
for animation.
This is how you can start, this is simple bar chart with grid decoration:
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Chart(
state: ChartState.bar(
ChartData.fromList(
[1, 3, 4, 2, 7, 6, 2, 5, 4]
.map((e) => BarValue<void>(e.toDouble()))
.toList(),
),
itemOptions: const BarItemOptions(
padding: EdgeInsets.symmetric(horizontal: 2.0),
radius: BorderRadius.vertical(top: Radius.circular(12.0)),
),
backgroundDecorations: [
GridDecoration(
verticalAxisStep: 1,
horizontalAxisStep: 1,
gridColor: Theme.of(context).dividerColor,
),
],
foregroundDecorations: [
BorderDecoration(
color: Theme.of(context).colorScheme.secondary,
borderWidth: 2.0,
),
],
),
),
);
}
To turn any chart to line chart we just need to add SparklineDecoration
to foregroundDecorations
or backgroundDecorations
. This will add decoration line on top/bottom of the chart.
By replacing the BarValue
to BubbleValue
and changing geometryPainter
to bubblePainter
we can show nicer line chart with small bubbles on data points:
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Chart(
state: ChartState.line(
ChartData.fromList(
/// CHANGE: Change [BarValue<void>] to [BubbleValue<void>]
[1, 3, 4, 2, 7, 6, 2, 5, 4]
.map((e) => BubbleValue<void>(e.toDouble()))
.toList(),
),
/// CHANGE: From [BarItemOptions] to [BubbleItemOptions]
itemOptions: const BubbleItemOptions(
padding: EdgeInsets.symmetric(horizontal: 2.0),
/// REMOVED: Radius doesn't exist in [BubbleItemOptions]
// radius: BorderRadius.vertical(top: Radius.circular(12.0)),
/// ADDED: Make [BubbleValue] items smaller
maxBarWidth: 4.0,
),
backgroundDecorations: [
GridDecoration(
verticalAxisStep: 1,
horizontalAxisStep: 1,
gridColor: Theme.of(context).dividerColor,
),
],
foregroundDecorations: [
BorderDecoration(
color: Theme.of(context).colorScheme.secondary,
borderWidth: 2.0,
),
/// ADDED: Add spark line decoration ([SparkLineDecoration]) on foreground
SparkLineDecoration(),
],
),
),
);
}
Code above will make our nicer line graph:
Charts can have multiple values that are grouped.
To turn any chart to multi value we need to use ChartState
instead of ChartState.fromList
constructor. Default constructor will accept List<List<ChartItem<T>>
allowing us to pass multiple lists to same chart.
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Chart(
/// CHANGE: From [ChartState.fromList] to [ChartState]
state: ChartState(
/// CHANGE: Add list we had into bigger List
ChartData(
[
[1, 3, 4, 2, 7, 6, 2, 5, 4]
.map((e) => BubbleValue<void>(e.toDouble()))
.toList(),
/// ADD: Another list
[4, 6, 3, 3, 2, 1, 4, 7, 5]
.map((e) => BubbleValue<void>(e.toDouble()))
.toList(),
],
),
itemOptions: BubbleItemOptions(
padding: const EdgeInsets.symmetric(horizontal: 2.0),
maxBarWidth: 4.0,
/// ADDED: Color bubbles differently depending on List they came from. [ColorForIndex]
colorForKey: (item, index) {
return [
Theme.of(context).colorScheme.primary,
Theme.of(context).colorScheme.primaryVariant
][index];
},
),
backgroundDecorations: [
GridDecoration(
verticalAxisStep: 1,
horizontalAxisStep: 1,
gridColor: Theme.of(context).dividerColor,
),
],
foregroundDecorations: [
SparkLineDecoration(),
/// ADDED: Add another [SparkLineDecoration] for the second list
SparkLineDecoration(
// Specify key that this [SparkLineDecoration] will follow
// Throws if `lineArrayIndex` does not exist in chart data
lineArrayIndex: 1,
lineColor: Theme.of(context).colorScheme.primaryVariant,
),
BorderDecoration(
color: Theme.of(context).colorScheme.secondary,
borderWidth: 2.0,
),
],
),
),
);
}
Code above will make this multi line graph:
- Setting
isScrollable
totrue
will make the chart ignore it's specified width and should be wrapped in some Scrollable widget in order to display properly. - Get selected item,
onItemClick
will return index of the clicked item. - Change how multiple values in the map get drawn,
multiItemStack
by default is set totrue
, and multiple items will just stack on same place, setting this tofalse
will divide that place for each item, and they will be shown ingrouped
state.
Line chart with multiple values example code
Bar chart with area example code
Scrollable bar chart example code