文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

基于Flutter制作一个吃豆人加载动画

2024-04-02 19:55

关注

效果图

国际惯例,先看效果图:

具体效果就是吃豆人会根据吃不同颜色的豆子改变身体的颜色。

绘制静态吃豆人、豆豆、眼睛

首先,我们需要将这个静态的吃豆人绘制出来,我们可以把吃豆人看做是一个实心圆弧,豆豆和眼睛就是一个圆。

关键代码:

//画头
_paint
  ..color = color.value
  ..style = PaintingStyle.fill;
var rect = Rect.fromCenter(
    center: Offset(0, 0), width: size.width, height: size.height);
/// 起始角度
var a =  40 / 180 * pi;
// 绘制圆弧
canvas.drawArc(rect, 0, 2 * pi - a * 2, true, _paint);

// 画豆豆
canvas.drawOval(
    Rect.fromCenter(
        center: Offset(
            size.width / 2 +
                ddSize -
                angle2.value * (size.width / 2 + ddSize),
            0),
        width: ddSize,
        height: ddSize),
    _paint..color = color2.value);

//画眼睛
canvas.drawOval(
    Rect.fromCenter(
        center: Offset(0, -size.height / 3), width: 8, height: 8),
    _paint..color = Colors.black87);

动画属性: 嘴巴的张合:通过圆弧的角度不断改变实现,豆豆移动:从头的右侧源源不断的有豆子向左移动,改变豆豆x轴的坐标即可,接下来我们让吃豆人动起来吧。

加入动画属性

这里我们需要创建2个动画控制器,一个控制头,一个控制豆豆,我们看到因为头部一开一合属于动画正向执行一次然后再反向执行一次,相当于执行了两次,豆豆的从右边到嘴巴只执行了一次,所以头的执行时间是豆豆执行时间的两倍,嘴巴一张一合才能吃豆子嘛,吃豆完毕,将豆子颜色赋值给头改变颜色,豆子随机获取另一个颜色,不断的吃豆。 这里的绘制状态有多种情况,嘴巴的张合、豆子的平移、颜色的改变都需要进行重新绘制,这里我们可以使用 Listenable.merge方法来进行监听,接受一个Listenable数组,可以将我们需要改变的状态放到这个数组里,返回一个 Listenable赋值给CustomPainter构造函数repaint属性即可,然后在监听只需判断这个Listenable即可。

factory Listenable.merge(List<Listenable?> listenables) = _MergingListenable;

关键代码: 动画执行相关。

late Animation<double> animation; // 吃豆人
late Animation<double> animation2; // 豆豆
late AnimationController _controller = AnimationController(
    vsync: this, duration: Duration(milliseconds: 500)); //1s
late AnimationController _controller2 = AnimationController(
    vsync: this, duration: Duration(milliseconds: 1000)); //2s

//初始化吃豆人、豆豆颜色
ValueNotifier<Color> _color = ValueNotifier<Color>(Colors.yellow.shade800);
ValueNotifier<Color> _color2 =
    ValueNotifier<Color>(Colors.redAccent.shade400);

// 动画轨迹
late CurvedAnimation cure = CurvedAnimation(
    parent: _controller, curve: Curves.easeIn); // 动画运行的速度轨迹 速度的变化

@override
void initState() {
  super.initState();
  animation = Tween(begin: 0.2, end: 1.0).animate(_controller)
    ..addStatusListener((status) {
      // dismissed 动画在起始点停止
      // forward 动画正在正向执行
      // reverse 动画正在反向执行
      // completed 动画在终点停止
      if (status == AnimationStatus.completed) {
        _controller.reverse(); //反向执行 100-0
      } else if (status == AnimationStatus.dismissed) {
        _color.value = _color2.value;
        // 获取一个随机彩虹色
        _color2.value = getRandomColor();
        _controller.forward(); //正向执行 0-100
        // 豆子已经被吃了 从新加载豆子动画
        _controller2.forward(from: 0); //正向执行 0-100
      }
    });
animation2 = Tween(begin: 0.2, end: 1.0).animate(_controller2);
  // 启动动画 正向执行
  _controller.forward();
  // 启动动画 0-1循环执行
  _controller2.forward();
  // 这里这样重复调用会导致两次动画执行时间不一致 时间长了就不对应了
  // _controller2.repeat();
}

@override
void dispose() {
  _controller.dispose();
  _controller2.dispose();

  super.dispose();
}

@override
Widget build(BuildContext context) {
  return Center(
      child: CustomPaint(
    size: Size(50, 50),
    painter: Pain2Painter(
        _color,
        _color2,
        animation,
        animation2,
        Listenable.merge([
          animation,
          animation2,
          _color,
        ]),
        ddSize: 8),
  ));
}

// 获取一个随机颜色
Color getRandomColor() {
  Random random = Random.secure();
  int randomInt = random.nextInt(6);
  var colors = <Color>[
    Colors.red,
    Colors.orange,
    Colors.yellow,
    Colors.green,
    Colors.blue,
    Colors.indigo,
    Colors.purple,
  ];
  Color color = colors[randomInt];
  while (color == _color2.value) {
    // 重复再选一个
    color = colors[random.nextInt(6)];
  }
  return color;
}

绘制吃豆人源码:

class Pain2Painter extends CustomPainter {
  final ValueNotifier<Color> color; // 吃豆人的颜色
  final ValueNotifier<Color> color2; // 豆子的的颜色
  final Animation<double> angle; // 吃豆人
  final Animation<double> angle2; // 豆
  final double ddSize; // 豆豆大小
  final Listenable listenable;

  Pain2Painter(
      this.color, this.color2, this.angle, this.angle2, this.listenable,
      {this.ddSize = 6})
      : super(repaint: listenable);
  Paint _paint = Paint();

  @override
  void paint(Canvas canvas, Size size) {
    canvas.clipRect(Offset.zero & size);
    canvas.translate(size.width / 2, size.height / 2);
    // 画豆豆
    canvas.drawOval(
        Rect.fromCenter(
            center: Offset(
                size.width / 2 +
                    ddSize -
                    angle2.value * (size.width / 2 + ddSize),
                0),
            width: ddSize,
            height: ddSize),
        _paint..color = color2.value);
    //画头
    _paint
      ..color = color.value
      ..style = PaintingStyle.fill;

    var rect = Rect.fromCenter(
        center: Offset(0, 0), width: size.width, height: size.height);

    /// 起始角度
    /// angle.value 动画控制器的值 0.2~1 0是完全闭合就是 起始0~360° 1是完全张开 起始 40°~ 280° 顺时针
    var a = angle.value * 40 / 180 * pi;
    // 绘制圆弧
    canvas.drawArc(rect, a, 2 * pi - a * 2, true, _paint);
    //画眼睛
    canvas.drawOval(
        Rect.fromCenter(
            center: Offset(0, -size.height / 3), width: 8, height: 8),
        _paint..color = Colors.black87);
canvas.drawOval(
    Rect.fromCenter(
        center: Offset(-1.5, -size.height / 3 - 1.5), width: 3, height: 3),
    _paint..color = Colors.white);
  }

  @override
  bool shouldRepaint(covariant Pain2Painter oldDelegate) {
    return oldDelegate.listenable != listenable;
  }
}

至此,一个简单的吃豆人加载Loading就完成啦。再也不要到处都是菊花转的样式了。。。

总结

通过这个加载Loading动画可以重新复习下Flutter中绘制、动画的使用的联动使用、还有多状态重绘机制,通过动画还可以改变吃豆的速度和吃豆的时间运动轨迹,有兴趣可以试试哦。

以上就是基于Flutter制作一个吃豆人加载动画的详细内容,更多关于Flutter加载动画的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯