zoukankan      html  css  js  c++  java
  • Flutter 动画鼻祖之CustomPaint

    老孟导读:CustomPaint可以称之为动画鼻祖,它可以实现任何酷炫的动画和效果。CustomPaint本身没有动画属性,仅仅是绘制属性,一般情况下,CustomPaint会和动画控制配合使用,达到理想的效果。

    基本用法

    CustomPaint的用法非常简单,如下:

    CustomPaint(
      painter: MyCustomPainter(),
    )
    

    MyCustomPainter定义如下:

    class MyCustomPainter extends CustomPainter {
      @override
      void paint(Canvas canvas, Size size) {}
    
      @override
      bool shouldRepaint(MyCustomPainter oldDelegate) {
        return this != oldDelegate;
      }
    }
    

    上面的MyCustomPainter为了看起来清晰,什么也没有做,通常情况下,在paint方法内绘制自定义的效果。shouldRepaint方法通常在当前实例和旧实例属性不一致时返回true。

    paint通过canvas绘制,size为当前控件的大小,下面看看canvas的方法。

    绘制点

    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);
      }
    

    image-20200601094814789

    PointMode有3种模式:

    • points:点
    • lines:将2个点绘制为线段,如果点的个数为奇数,最后一个点将会被忽略
    • polygon:将整个点绘制为一条线

    绘制线

    canvas.drawLine(Offset(0, 0),Offset(size.width, size.height), _paint);
    

    image-20200601095248302

    绘制路径

    Paint _paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3;
    
    @override
    void paint(Canvas canvas, Size size) {
      print('size:$size');
      var _path = Path()
        ..moveTo(0, 0)
        ..lineTo(size.width, 0)
        ..lineTo(size.width, size.height)
      ..close();
      canvas.drawPath(_path, _paint);
    }
    

    image-20200601110532164

    这里注意Paint.style,还可以设置为PaintingStyle.fill,效果如下:

    image-20200601110642252

    此时Path的路径不要在一条直线上,否则会看不到效果。

    绘制各种形状

    绘制圆形

    canvas.drawCircle(Offset(size.width/2, size.height/2), 20, _paint);
    

    image-20200601111802952

    绘制椭圆

    canvas.drawOval(Rect.fromLTRB(0, 0, size.width, size.height/2), _paint);
    

    image-20200601111910120

    如果给定的Rect为正方形,那么椭圆将会变为圆形。

    绘制弧

    canvas.drawArc(
        Rect.fromLTRB(0, 0, size.width, size.height), 0, pi/2, true, _paint);
    

    image-20200601112255715

    绘制圆角矩形

    canvas.drawRRect(
        RRect.fromLTRBR(0, 0, size.width, size.height, Radius.circular(10)), _paint)
    

    image-20200601112830212

    canvas还有很多绘制函数,比如贝塞尔曲线、三次贝塞尔曲线、画布的反转等操作,这里不在一一介绍。

    这些函数和Android的Canvas基本一样,如果你有Android基础,直接套用即可。

    最后奉上一个绘制玫瑰的动画效果:

    rose_gif

    这个效果是不是很酷炫,我们看下绘制花骨朵代码:

    ///
    /// 绘制花骨朵
    ///
    _drawFlower(Canvas canvas, Size size) {
      //将花变为红色
      if (flowerPaths.length >= RoseData.flowerPoints.length) {
        var path = Path();
        for (int i = 0; i < flowerPaths.length; i++) {
          if (i == 0) {
            path.moveTo(flowerPaths[i].dx, flowerPaths[i].dy);
          } else {
            path.lineTo(flowerPaths[i].dx, flowerPaths[i].dy);
          }
        }
        _paint.style = PaintingStyle.fill;
        _paint.color = _flowerColor;
        canvas.drawPath(path, _paint);
      }
      //绘制线
      _paint.style = PaintingStyle.stroke;
      _paint.color = _strokeColor;
      //去掉最后2个点,最后2个点为了绘制红色
      var points = flowerPaths.sublist(0, max(0, flowerPaths.length - 2));
      canvas.drawPoints(PointMode.polygon, points, _paint);
    }
    

    花骨朵的绘制只通过canvas.drawPath就实现了,其实整个玫瑰花的绘制都是通过canvas.drawPath加上动画控制实现的。

    CustomPaint可以实现任何你想要的动画的效果,比如绘画版就可以通过此控件实现。

    获取完整代码方式扫码下方二维码回复:rose

    交流

    老孟Flutter博客地址(近200个控件用法):http://laomengit.com

    欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:

  • 相关阅读:
    模块
    Queue(队列)
    Stack(栈)
    Vector(容器)
    位图像素的颜色
    大数处理之三(除法)
    大数处理之二(幂运算)
    浮点数(double)的优势
    大数处理之一(加法和乘法)
    Depth-First Search
  • 原文地址:https://www.cnblogs.com/mengqd/p/13034117.html
Copyright © 2011-2022 走看看