美文网首页
Flutter: 自绘整理 CustomPaint

Flutter: 自绘整理 CustomPaint

作者: 李小轰 | 来源:发表于2021-08-26 16:56 被阅读0次
    序言

    最近仿照网上的案例,学习了 CustomPaint 的绘制使用。万丈高楼平地起,每天学习,每天进步。下面把 CustomPaint 在使用过程中的重点记录一下。

    基本用法

    父层 CustomPaint 是固定写法,painter 入参是我们真实的绘制实现,size 用于指定画布大小,不指定时,画布大小为 child 的大小。

    CustomPaint(
      size: Size(200, 200), //指定画布大小
      painter: MyPainter(), //自定义的绘制内容
      child: RepaintBoundary(child)), 
    )
    

    如果 CustomPaint 有子节点,为了避免子节点不必要的重绘并提高性能,通常情况下都会将子节点包裹在 RepaintBoundary 组件中。

    MyPainter 如何使用?

    新建 MyPainter 继承 CustomPainter , 并重写如下两个方法:

    • void paint(Canvas canvas, Size size): 在这里面,配合 canvaspaint 完成自定义绘制
    • bool shouldRepaint(covariant MyPainter old): 在实际场景中正确利用此回调可以避免重绘开销
    具体样例

    CustomPaint 基础知识结合 anitaion 动画实现如下demo :

    我们把实现分为两个部分:

    1. 实现扇形绘制,弧度由构造方法传入
    class _PacmanPainter extends CustomPainter {
      final double angle;
      final Color color;
    
      Paint _paint = Paint()..style = PaintingStyle.fill;
    
      _PacmanPainter(this.angle, this.color) {
        _paint.color = color;
      }
    
      @override
      void paint(Canvas canvas, Size size) {
        final _radius = min(size.width, size.height) / 2;
        ///根据 angle 绘制扇形
        canvas.drawArc(Rect.fromLTWH(0, 0, _radius * 2, _radius * 2), angle / 2,
            2 * pi - angle, true, _paint);
      }
    
      @override
      bool shouldRepaint(covariant _PacmanPainter old) {
        return color != old.color || angle != old.angle;
      }
    }
    
    1. 封装动画层,根据进度控制 _PacmanPainter 进行重绘
    class _TestPacmanWidgetState extends State<TestPacmanWidget>
        with TickerProviderStateMixin {
      AnimationController _controller, _controller1;
      Animation<double> _animation;
    
      @override
      void initState() {
        _controller = AnimationController(
          vsync: this,
          duration: const Duration(milliseconds: 800),
        )..repeat(reverse: true);
        //执行 repeat 动画就开始了,reverse 设置动画正序倒序循环
        _animation = Tween(begin: 0.0, end: pi / 2).animate(
          CurvedAnimation(
            parent: _controller,
            curve: Curves.linear,
          ),
        );
        super.initState();
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          height: 200,
          width: 200,
          child: AnimatedBuilder(
            animation: _animation,
            builder: (context, child) {
              return CustomPaint(
                painter: _PacmanPainter(
                  _animation.value,
                  Colors.blue,
                ),
              );
            },
          ),
        );
      }
    }
    

    AnimatedBuilder 内部实现监听动画进度,并触发 setState,在 builder: (context, child) 中响应重绘。_pacmanPainter 使用 _animation.value 这个变化值作为入参,最终实现动画效果。


    快捷代码笔记:
    • 画点
    Paint _paint = Paint()
        ..color = Colors.red
        ..strokeWidth = 3;
    
      @override
      void paint(Canvas canvas, Size size) {
        var points = [
          Offset(0, 0),
          Offset(size.width / 2, size.height / 2),
          Offset(size.width, size.height),
        ];
        canvas.drawPoints(PointMode.points, points, _paint);
      }
    
    • 画线
      canvas.drawLine(Offset(0, 0),Offset(size.width, size.height), _paint);
    • 画路径
    Paint _paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3;
    
    @override
    void paint(Canvas canvas, Size size) {
      var _path = Path()
        ..moveTo(0, 0)
        ..lineTo(size.width, 0)
        ..lineTo(size.width, size.height)
      ..close();
      canvas.drawPath(_path, _paint);
    }
    
    • 画圆形
      canvas.drawCircle(Offset(size.width/2, size.height/2), 20, _paint);
    • 画扇形(圆弧)
      canvas.drawArc( Rect.fromLTRB(0, 0, size.width, size.height), 0, pi/2, true, _paint);

    drawArc 方法参数说明:
    rect 构造矩形
    startAngle 开始角度
    sweepAngle 绘制的弧形占用角度弧度(360°角=2π)
    userCenter 扇形或圆弧段(true或false)

    相关文章

      网友评论

          本文标题:Flutter: 自绘整理 CustomPaint

          本文链接:https://www.haomeiwen.com/subject/udruiltx.html