Flutter 轮子之下雪动画(2)

Flutter 轮子之下雪动画,底部也有Android的下雪动画,记得点赞哦~

还是老套路,先来看看今天要完成的效果:
在这里插入图片描述
首页的二维码是我的公众号,随后我会上传到公众号上

今天要完成的是最后的下雪动画~

先来分析一波:

  • 随机大小的雪花(圆)
  • 可以使雪花(圆)左右偏移
  • 雪花(圆)向右下角方向垂直移动
  • 雪花(圆)当消失之后会重复创建执行

画圆

先给大家介绍怎么画一个圆


 @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.black,
      child: CustomPaint(
        painter: MyCustomPainter(),
        //占满屏幕
        size: MediaQuery.of(context).size,
      ),
    );
  }


class MyCustomPainter extends CustomPainter {
//创建画笔
  Paint _paint = new Paint()
    ..isAntiAlias = true
    ..color = Colors.white;

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawCircle(Offset(100,100), 50, _paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
  //刷新
    return true;
  }
}

可以参考文档Flutter 轮子之气泡登录页来了解这部分代码

效果图(1.1):
在这里插入图片描述
吧他写成类的形式:

创建雪花Bean类

class SnowBean {
  //位置
  Offset postion = Offset(100,100);

  //半径
  double radius = 50;
}


class MyCustomPainter extends CustomPainter {
  //创建画笔
   Paint _paint = new Paint()
    ..isAntiAlias = true
    ..color = Colors.white;
  @override
  void paint(Canvas canvas, Size size) {
   SnowBean snowBean = new SnowBean();
    canvas.drawCircle(snowBean.postion, snowBean.radius, _paint);
  }
  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) { .... }
}

效果图(1.2):
在这里插入图片描述
这部分代码很简单,就不说了.

创建200个随机圆并绘制

List<SnowBean> _list = [];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    Future.delayed(Duration(seconds: 0), () {
      initData();
    });
  }

  void initData() {
    for (int i = 0; i <= 200; i++) {
      SnowBean snowBean = new SnowBean();
	//MediaQuery.of(context).size.width是屏幕的宽
	//MediaQuery.of(context).size.height是屏幕的高
      double dx = _random.nextDouble() * MediaQuery.of(context).size.width;
      double dy = _random.nextDouble() * MediaQuery.of(context).size.height;
       snowBean.postion = Offset(dx, dy);
      snowBean.radius = _random.nextDouble() + 1;
      _list.add(snowBean);
    }
  }


class MyCustomPainter extends CustomPainter {
  //创建画笔
  .....
    List<SnowBean> list;

  MyCustomPainter(this.list);
  @override
  void paint(Canvas canvas, Size size) {
    list.forEach((element) {
      canvas.drawCircle(element.postion, element.radius, _paint);
    });
  }
  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) { .... }
}

这段代码非常简单,就是在initState()初始化的时候,使用异步创建200个随机大小,随机位置的圆,并吧这个list传递给MyCustomPainter(),然他绘制出每一个圆

来看看效果吧:
在这里插入图片描述
现在是不是就很有感觉了~

设置动画

AnimationController _animationController;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    //创建动画,执行为1秒
    _animationController =
        new AnimationController(vsync: this, duration: Duration(seconds: 10));

    //动画监听器
    _animationController.addListener(() {
      setState(() {});
    });

    //重复执行气泡动画
    _animationController.repeat();
  }

这段代码参考Flutter AnimatedWidget,AnimatedBuilder动画(2.4)

接下来重新写一下MyCustomPainter ()方法

class MyCustomPainter extends CustomPainter {
  List<SnowBean> list;
  Random _random;

  MyCustomPainter(this.list, this._random);

  Paint _paint = new Paint()
    ..isAntiAlias = true
    ..color = Colors.white;

  @override
  void paint(Canvas canvas, Size size) {

    list.forEach((element) {
      double dy = element.postion.dy;
      double dx = element.postion.dx;

      /**
       * 若Y轴雪花移动到屏幕以外,则让它回到起始位置
       */
      if (dy >= size.height) {
        dy = 0;
      }
      /**
       * 若X轴雪花移动到屏幕以外,则让它回到起始位置
       */
      if (dx >= size.width) {
        dx = 0;
      }

      element.postion =
          Offset(dx + _random.nextDouble(), dy + _random.nextDouble() + element.speed + 3);
    });

    list.forEach((element) {
      canvas.drawCircle(element.postion, element.radius, _paint);
    });
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}

SnowBean添加移动的速度:
class SnowBean {
  //位置
  Offset postion = Offset(100, 100);

  //半径
  double radius = 50;

  //移动速度
  double speed;
}

重新初始化:
 void initData() {
    for (int i = 0; i <= 200; i++) {
      SnowBean snowBean = new SnowBean();

	  //_random.nextDouble()是0-1随机的小数
      double dx = _random.nextDouble() * MediaQuery.of(context).size.width;
      double dy = _random.nextDouble() * MediaQuery.of(context).size.height;
      snowBean.postion = Offset(dx, dy);
      snowBean.radius = _random.nextDouble() + 1;
      snowBean.speed = _random.nextDouble() + 5;

      _list.add(snowBean);
    }
  }


这段代码我相信大家看到大部分还是可以看懂的;

给大家解释一下这段代码:

  /**
       * 若Y轴雪花移动到屏幕以外,则让它回到起始位置
       */
      if (dy >= size.height) {
        dy = 0;
      }
      /**
       * 若X轴雪花移动到屏幕以外,则让它回到起始位置
       */
      if (dx >= size.width) {
        dx = 0;
      }

这段代码的意思是,当dx或者dy移动出屏幕时,让他重新绘制

 element.postion =
         Offset(dx + _random.nextDouble(),
          dy +  element.speed );
  • 参数一:dx 加 _random.nextDouble() 代表的是当前的经度加上一个0-1的随机数,有一个左右偏移的动画效果
  • 参数二:dy加一个下降的运行速度为当前的dy的值

来看看效果:
在这里插入图片描述
可能有同学还是会疑惑,让动画重复执行了,可是为什么雪花会动呢?

注意看这个setState(){}方法
在这里插入图片描述
其实啊:这里的setState(){}这个方法,一直在执行sholdRepaint方法()
在这里插入图片描述
先会判断这里的返回值,如果是true则会一直刷新paint()方法,paint()中的操作简单理解就是让dx左右移动,dy一直向下移动,当移动到屏幕外时,则让它回到起始位置,则达到一直’下雪’的效果,如果返回的是false,则只执行一次

完整代码

猜你喜欢:

Flutter 轮子之气泡登录页(1)

Android 轮子之下雪效果

原创不易,您的点赞就是对我最大的支持,留下您的点赞吧~

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

s10g

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值