Skip to content

Instantly share code, notes, and snippets.

@Barttje
Last active September 12, 2020 08:27
Show Gist options
  • Save Barttje/356ac18aab7835656d2d4e4eed0fb6e7 to your computer and use it in GitHub Desktop.
Save Barttje/356ac18aab7835656d2d4e4eed0fb6e7 to your computer and use it in GitHub Desktop.
Simpel bar chart animation with AnimatedBuilder
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(BarChartAnimationDemo());
}
class BarChartAnimationDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Bar chart demo"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: BarChart(),
),
),
);
}
}
class BarChart extends StatefulWidget {
@override
_BarChartState createState() => _BarChartState();
}
class _BarChartState extends State<BarChart>
with SingleTickerProviderStateMixin {
Map<String, int> data = {
"Banana": 16,
"Orange": 8,
"Apple": 10,
"Kiwi": 10,
"Pear": 3,
};
@override
Widget build(BuildContext context) {
return TweenAnimationBuilder(
tween: Tween<double>(begin: 0, end: 100),
duration: Duration(seconds: 1),
builder: (BuildContext context, double percentage, Widget child) {
return CustomPaint(
painter: BarChartPainter(data, "Favorite Fruit", percentage),
child: Container(
width: 350,
),
);
});
}
}
class BarChartPainter extends CustomPainter {
final String title;
final Map<String, int> data;
// Currently based on the length of the category names
double marginTopX = 0;
double marginTopY;
//padding between the bars
final double paddingY = 5;
final double axisWidth = 2;
final double barHeight = 15;
final double percentage;
BarChartPainter(this.data, this.title, this.percentage) {
// determine where to begin with X, based on the width of the category names
data.forEach((key, value) {
var text = createText(key, 1);
if ((text.width + 5) > marginTopX) {
marginTopX = text.width + 5;
}
});
marginTopY = createText(title, 1.5).height + paddingY;
}
@override
void paint(Canvas canvas, Size size) {
Paint axis = Paint()
..strokeWidth = axisWidth
..color = Colors.grey;
double number = 0;
data.forEach((key, value) {
drawBar(canvas, size, number, key, value);
number++;
});
drawAxes(canvas, size, axis);
drawTitle(canvas, size);
}
void drawTitle(Canvas canvas, Size size) {
TextPainter tp = createText(title, 1.5);
tp.paint(canvas, new Offset(size.width / 2 - tp.width / 2, 0));
}
void drawAxes(Canvas canvas, Size size, Paint axis) {
canvas.drawLine(
Offset(marginTopX,
data.entries.length * (paddingY + barHeight) + marginTopY),
Offset(size.width,
data.entries.length * (paddingY + barHeight) + marginTopY),
axis,
);
canvas.drawLine(
Offset(marginTopX,
data.entries.length * (paddingY + barHeight) + marginTopY),
Offset(marginTopX, marginTopY - paddingY),
axis,
);
}
void drawBar(Canvas canvas, Size size, double number, String key, int value) {
double y = number * (paddingY + barHeight) + marginTopY + barHeight / 2;
drawText(key, canvas, y);
Paint paint = Paint()
..strokeWidth = barHeight
..color = Colors.green;
final barWidth = (size.width - marginTopX) / (maxValue() / value);
final currentMaxWidth = (size.width - marginTopX) * percentage / 100;
final width = min(currentMaxWidth, barWidth);
canvas.drawLine(
Offset(marginTopX, y),
Offset(width + marginTopX, y),
paint,
);
}
void drawText(String key, Canvas canvas, double y) {
TextPainter tp = createText(key, 1);
tp.paint(canvas, new Offset(0, y - tp.height / 2));
}
TextPainter createText(String key, double scale) {
TextSpan span =
new TextSpan(style: new TextStyle(color: Colors.grey[600]), text: key);
TextPainter tp = new TextPainter(
text: span,
textAlign: TextAlign.left,
textScaleFactor: scale,
textDirection: TextDirection.ltr);
tp.layout();
return tp;
}
@override
bool shouldRepaint(BarChartPainter oldDelegate) =>
this.percentage != oldDelegate.percentage;
int maxValue() => data.values.reduce(max);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment