So tired, it’s really bothersome not to plug in
This blogger uses flutter to create pie charts purely by hand, drawing on canvas, so tired, remember to collect and learn, my little fans~
The old rules, look at the effect
of the code:
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: piepage(),
);
}
}
class piepage extends StatefulWidget {
@override
_piepageState createState() => _piepageState();
}
Color mainColor = Color(0xFFCADCED);
class _piepageState extends State<piepage> with SingleTickerProviderStateMixin {
AnimationController _animationController;
Animation<double> _bgAnimation;
Animation<double> _progressAnimation;
Animation<double> _numberAnimation;
@override
void initState() {
super.initState();
_animationController = new AnimationController(
duration: Duration(milliseconds: 1000), vsync: this);
_bgAnimation = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
parent: _animationController,
curve: Interval(0.0, 0.5),
));
_progressAnimation = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
parent: _animationController,
curve: Interval(0.4, 0.8),
));
_numberAnimation = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
parent: _animationController,
curve: Interval(0.7, 1.0),
));
_animationController.addListener(() {
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
height: 260,
width: MediaQuery.of(context).size.width,
//背景
color: mainColor,
//封装方法
child: buildRow(),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
_animationController.reset();
_animationController.forward();
},
),
);
}
//定义数据模型
List _list = [
{"title": "生活费", "number": 200, "color": Colors.lightBlueAccent},
{"title": "伙食费", "number": 200, "color": Colors.deepOrangeAccent},
{"title": "交通费", "number": 400, "color": Colors.green},
{"title": "网购", "number": 300, "color": Colors.red},
{"title": "电话费", "number": 200, "color": Colors.orange}
];
buildRow() {
return Row(
children: [
Expanded(
flex: 5,
child: buildLeftColumn(), //左边
),
//饼图区域
Expanded(
flex: 6,
child: Stack(
alignment: Alignment.center,
children: [
//第一层
Container(
padding: EdgeInsets.all(22),
decoration: BoxDecoration(
color: mainColor,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.white,
spreadRadius: -8 * _bgAnimation.value,
offset: Offset(
-5 * _bgAnimation.value, -5 * _bgAnimation.value),
//阴影偏移量
blurRadius: 30 * _bgAnimation.value,
),
BoxShadow(
color: Colors.blue[300].withOpacity(0.3),
spreadRadius: 2 * _bgAnimation.value,
offset: Offset(
5 * _bgAnimation.value, 5 * _bgAnimation.value),
//阴影偏移量
blurRadius: 20 * _bgAnimation.value,
)
]),
//开始绘制
child: CustomPaint(
size: Size(200, 200),
painter:
CustomShapePainter(_list, _progressAnimation.value),
),
),
],
))
],
);
}
//左边
Column buildLeftColumn() {
return Column(
mainAxisSize: MainAxisSize.min,
children: _list.map(
(data) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
children: [
Container(
margin: EdgeInsets.only(right: 10),
width: 10,
height: 10,
decoration: BoxDecoration(
color: data['color'],
shape: BoxShape.circle,
),
),
Text(
data['title'],
style: TextStyle(fontSize: 16),
)
],
));
},
).toList(),
);
}
}
class CustomShapePainter extends CustomPainter {
List list;
double progress;
CustomShapePainter(this.list, this.progress);
Paint _paint = new Paint()..isAntiAlias = true;
@override
void paint(Canvas canvas, Size size) {
//中心
Offset center = Offset(size.width / 2, size.height / 2);
//半径
double radius = min(size.width / 2, size.height / 2);
//弧度
double starRadian = -pi / 2;
double total = 0.0;
list.forEach((element) {
total += element['number'];
});
for (var i = 0; i < list.length; i++) {
var item = list[i];
double flag = item['number'] / total;
double sweepRadin = flag * 2 * pi * progress;
_paint.color = item['color'];
canvas.drawArc(Rect.fromCircle(center: center, radius: radius),
starRadian, sweepRadin, true, _paint);
starRadian += sweepRadin;
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}