flutter: pie chart drawn by hand

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
Insert picture description here
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;
  }
}

Guess you like

Origin blog.csdn.net/weixin_45425105/article/details/114094493