Flutter 进阶:实现唯美的小心心雪花动画效果

实现唯美的小心心雪花动画效果

在这篇博客中,我们将带你一步步实现一个浪漫的小心心雪花动画效果。这个动画非常适合用于情人节主题、表白页面或者任何需要增加浪漫气息的应用场景。

我们将构建一个主要的 HeartFallAnimation widget 来管理和绘制我们的动画。

效果展示视频地址:https://live.csdn.net/v/417675
资源文件下载地址:https://download.csdn.net/download/yang_6799/89641781

1. 项目结构

整个项目基于一个单一的 StatefulWidget HeartFallAnimation,它将负责初始化、更新和绘制心形雪花。

2. 创建核心类和方法

首先,我们定义一个表示心形的 Heart 类。这个类包含 x 和 y 坐标,以及心形的下落速度。这样可以使每个心形以不同的速度从屏幕顶部掉落,模拟真实的雪花效果。

class Heart {
  double x, y, speed;

  Heart(this.x, this.y, this.speed);

  void updatePosition(double screenHeight) {
    y += speed;
    if (y > screenHeight) {
      y = -100; // 重置心形位置到屏幕顶部之外,使其重新开始下落
      x = Random().nextDouble() * screenHeight; // 随机重置x坐标
    }
  }
}
  • x 和 y:心形在屏幕上的位置。
  • speed:心形的下落速度,每个心形的速度是随机的。
  • updatePosition 方法:更新心形的位置。如果心形超出了屏幕底部,它会被重置到屏幕顶部之外并赋予新的 x 坐标。

接下来,我们实现 HeartFallPainter,这个类负责绘制所有下落的心形:

class HeartFallPainter extends CustomPainter {
  final List<Heart> hearts;
  final Paint heartPaint = Paint()..color = Colors.red;

  HeartFallPainter(this.hearts);

  @override
  void paint(Canvas canvas, Size size) {
    for (var heart in hearts) {
      drawHeart(canvas, heart.x, heart.y, size.width / 40); // 调整心形的大小
    }
  }

  void drawHeart(Canvas canvas, double x, double y, double size) {
    final path = Path();

    path.moveTo(x, y);
    path.cubicTo(
      x - size / 2, y - size / 2,
      x - size, y + size / 3,
      x, y + size,
    );
    path.moveTo(x, y);
    path.cubicTo(
      x + size / 2, y - size / 2,
      x + size, y + size / 3,
      x, y + size,
    );

    canvas.drawPath(path, heartPaint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}
  • hearts:传递给画家的一组心形对象。
  • heartPaint:设置心形的颜色为红色。
  • paint 方法:遍历所有心形并调用 drawHeart 方法进行绘制。
  • drawHeart 方法:在指定位置绘制心形路径。使用贝塞尔曲线来绘制心形的左右两半。

然后,我们创建 HeartFallAnimation 这个 StatefulWidget 它将控制心形动画的逻辑:

class HeartFallAnimation extends StatefulWidget {
  @override
  _HeartFallAnimationState createState() => _HeartFallAnimationState();
}

class _HeartFallAnimationState extends State<HeartFallAnimation>
    with SingleTickerProviderStateMixin {
  AnimationController? _controller;
  List<Heart> hearts = [];
  static const int numberOfHearts = 200; // 增加小心心的数量

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: Duration(seconds: 5),
    )..repeat();

    _controller!.addListener(() {
      setState(() {
        for (var heart in hearts) {
          heart.updatePosition(MediaQuery.of(context).size.height);
        }
      });
    });
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // 初始化心形列表
    if (hearts.isEmpty) {
      final screenWidth = MediaQuery.of(context).size.width;
      for (int i = 0; i < numberOfHearts; i++) {
        double startX = Random().nextDouble() * screenWidth;
        double startY = -Random().nextDouble() * 1000;
        double fallSpeed = Random().nextDouble() * 2 + 1;
        hearts.add(Heart(startX, startY, fallSpeed));
      }
    }
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomPaint(
        painter: HeartFallPainter(hearts),
        child: Container(),
      ),
    );
  }
}

_HeartFallAnimationState 类包含以下重要部分:

  • AnimationController:控制动画的刷新频率。
    • _controller = AnimationController(vsync: this, duration: Duration(seconds: 5))…repeat(); 设置动画持续时间 5 秒钟并重复播放。
  • initState:初始化心形数据和动画控制器。
    • _controller!.addListener(() { … }):通过监听动画控制器的变化来不断更新心形位置。
  • didChangeDependencies:在依赖改变时(例如屏幕尺寸),初始化心形位置。
    • final screenWidth = MediaQuery.of(context).size.width; 获取屏幕宽度。
    • 使用 Random 类生成随机的初始位置和速度,为每个心形添加到 hearts 列表中。
  • dispose:释放动画控制器资源。
  • build:构建 UI,使用 CustomPaint 绘制心形。

3. 调整心形数量和大小

为了让效果更加显著,你可以根据需要调整心形的数量和大小。例如,在上面的代码中,我们将 numberOfHearts 设置为 200,并调整了心形大小。

static const int numberOfHearts = 200; // 调整心形数量

为了提高心形的密集度,我们将心形绘制尺寸调整为画布宽度的 1/40:

drawHeart(canvas, heart.x, heart.y, size.width / 40); // 调整心形大小

4. 总结

通过上述步骤,我们成功地创建了一个满屏小心心从顶部掉落的动画效果。这个动画不仅美观,还能为你的应用增添一份特别的浪漫氛围。

希望这篇博客能帮助你更好地理解如何使用动画和自定义绘图。如果你有任何问题或建议,欢迎在评论区留言!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值