flutter-使用confetti制作炫酷纸屑爆炸粒子动画

在 Flutter 开发中,粒子动画能为应用增添生动的视觉效果,比如节日庆祝、完成任务后的反馈等场景。confetti 库是实现纸屑爆炸动画的优质选择,它轻量、易用且支持高度自定义。下面我会详细介绍并添加实战案例。

1. 安装

首先需要在项目中集成 confetti 库,步骤如下:

1.1. 添加依赖

打开 pubspec.yaml 文件,在 dependencies 节点下添加最新版本的依赖:

yaml 复制代码
dependencies:
  flutter:
    sdk: flutter
  confetti: ^0.8.0 # 最新版本

1.2. 安装依赖

在终端执行命令安装依赖,或点击 Android Studio 中的Pub get按钮:

bash 复制代码
flutter pub get

1.3. 导入库

在需要使用动画的 Dart 文件中导入库:

dart 复制代码
import 'package:confetti/confetti.dart';

2. 核心 API 与参数解析

confetti 库的核心是 ConfettiWidget 组件和 ConfettiController 控制器,前者负责渲染动画,后者负责控制动画的播放、暂停、重置等。

2.1. 核心控制器:ConfettiController

ConfettiController 是动画的"大脑",通过它可以控制动画的生命周期。创建时需指定动画的持续时间、延迟时间等参数。

构造函数与关键参数

dart 复制代码
ConfettiController({
  required Duration duration, // 动画持续时间(必填)
  Duration delay = Duration.zero, // 动画延迟启动时间(默认0)
  double minInitialVelocity = 20, // 粒子初始最小速度(默认20)
  double maxInitialVelocity = 80, // 粒子初始最大速度(默认80)
  bool shouldLoop = false, // 动画是否循环(默认false)
  double gravity = 0.2, // 粒子下落的重力系数(默认0.2,值越大下落越快)
})

常用方法

方法名 作用
play() 启动动画(若已播放,会先重置再启动)
pause() 暂停动画
resume() 恢复暂停的动画
reset() 重置动画(粒子回到初始状态,停止播放)
dispose() 释放控制器资源(必须在页面销毁时调用)

2.2. 动画渲染:ConfettiWidget

ConfettiWidget 是渲染纸屑粒子的组件,需与 ConfettiController 绑定,同时支持自定义粒子的样式、方向、数量等。

构造函数与关键参数

dart 复制代码
ConfettiWidget({
  required ConfettiController confettiController, // 绑定控制器(必填)
  double blastDirection = pi, // 粒子爆炸方向(单位:弧度,默认向下,pi=180°)
  List<double> blastDirectionality = const [1], // 方向随机性([1]表示固定方向,[0.2, 0.8]表示20%-80%随机)
  double emissionFrequency = 0.05, // 粒子发射频率(值越小,每秒发射粒子越多,默认0.05=20个/秒)
  int numberOfParticles = 10, // 每次发射的粒子数量(默认10)
  double maxBlastForce = 20, // 粒子爆炸的最大力度(值越大,粒子扩散越远,默认20)
  double minBlastForce = 5, // 粒子爆炸的最小力度(默认5)
  bool shouldLoop = false, // 是否循环发射粒子(优先级低于控制器的shouldLoop)
  Widget? child, // 动画下方的子组件(如按钮、文本,动画会覆盖在子组件上方)
  Color color = Colors.white, // 粒子默认颜色(若设置particleColor则失效)
  List<Color>? particleColor, // 粒子颜色列表(随机使用列表中的颜色)
  double particleSize = 10, // 粒子默认大小(若设置particleWidget则失效)
  Widget? particleWidget, // 自定义粒子样式(如图片、图标,优先级最高)
  bool blastDirectionHasRandom = false, // 是否完全随机方向(覆盖blastDirectionality)
})

方向参数说明

blastDirection 使用弧度表示方向,常见方向对应值如下:

  • 向上:3 * pi / 2(或 -pi / 2
  • 向下:pi
  • 向左:pi(水平向左需结合 blastDirectionality 调整)
  • 向右:0(或 2 * pi
  • 右上:7 * pi / 4
  • 右下:pi / 4

3. 实战案例

下面通过一个简单案例,实现点击按钮后,从按钮位置向上发射彩色纸屑的效果:

完整代码

dart 复制代码
import 'package:confetti/confetti.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;

class ConfettiBasicDemo extends StatefulWidget {
  const ConfettiBasicDemo({super.key});

  @override
  State<ConfettiBasicDemo> createState() => _ConfettiBasicDemoState();
}

class _ConfettiBasicDemoState extends State<ConfettiBasicDemo> {
  // 1. 创建控制器:持续2秒,向上发射,重力0.1(下落慢)
  late final ConfettiController _confettiController;

  @override
  void initState() {
    super.initState();
    _confettiController = ConfettiController(
      duration: const Duration(seconds: 2),
      gravity: 0.1,
      minInitialVelocity: 30,
      maxInitialVelocity: 60,
    );
  }

  // 2. 页面销毁时释放控制器
  @override
  void dispose() {
    _confettiController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("基础纸屑动画")),
      body: Center(
        // 3. 用Stack包裹:让纸屑覆盖在按钮上方
        child: Stack(
          alignment: Alignment.center,
          children: [
            // 4. 纸屑动画组件
            ConfettiWidget(
              confettiController: _confettiController,
              blastDirection: math.pi * 3 / 2, // 向上发射(270°)
              emissionFrequency: 0.02, // 每秒50个粒子(1/0.02)
              numberOfParticles: 15, // 每次发射15个
              maxBlastForce: 30, // 最大爆炸力度
              minBlastForce: 10, // 最小爆炸力度
              particleColor: const [ // 随机彩色纸屑
                Colors.red,
                Colors.yellow,
                Colors.blue,
                Colors.green,
                Colors.pink,
              ],
              particleSize: 12, // 粒子大小
            ),

            // 5. 触发按钮
            ElevatedButton(
              onPressed: () {
                // 点击时启动动画(若已播放,先重置)
                _confettiController.play();
              },
              style: ElevatedButton.styleFrom(
                padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16),
                textStyle: const TextStyle(fontSize: 18),
              ),
              child: const Text("点击触发纸屑爆炸"),
            ),
          ],
        ),
      ),
    );
  }
}

效果说明

  • 点击按钮后,会从按钮位置向上发射彩色纸屑,持续2秒。
  • 粒子下落速度较慢(gravity: 0.1),且有随机的发射力度(10-30),呈现自然的扩散效果。

4. 常见问题与优化建议

下面是可能的一些问题与优化的建议,可以参考:

4.1. 动画卡顿

  • 减少粒子数量:降低 numberOfParticles(建议单次不超过30)。
  • 降低发射频率:增大 emissionFrequency(如从0.01改为0.03)。
  • 简化粒子样式:避免使用复杂的 particleWidget(如多层嵌套组件),优先用纯色或简单图标。

4.2. 让动画在指定位置触发

通过 StackalignmentPositioned 组件控制 ConfettiWidget 的位置。例如,让纸屑从顶部导航栏触发:

dart 复制代码
Stack(
  children: [
    // 其他页面内容
    Positioned(
      top: 0,
      left: 0,
      right: 0,
      child: ConfettiWidget(
        confettiController: _controller,
        blastDirection: math.pi / 2, // 向下发射
        // 其他参数...
      ),
    ),
  ],
)

4.3. 实现动画的循环

在创建 ConfettiController 时设置 shouldLoop: true,并将 duration 设为较大值(如 Duration(minutes: 1)),即可实现持续循环的纸屑效果(适合节日活动页面)。

5. 总结

confetti 库为 Flutter 开发者提供了低门槛、高自定义的粒子动画解决方案,核心是通过 ConfettiController 控制动画生命周期,通过 ConfettiWidget 自定义粒子样式与发射规则。无论是简单的点击反馈,还是复杂的节日氛围营造,都能通过它快速实现。

下面是官方的地址以及预览Demo:


本次分享就到这儿啦,我是鹏多多,如果看了觉得有帮助的,欢迎 点赞 关注 评论,在此谢过道友;

往期文章

相关推荐
ftpeak4 分钟前
Rust Web开发指南 第六章(动态网页模板技术-MiniJinja速成教程)
开发语言·前端·后端·rust·web
南囝coding22 分钟前
Claude Code 官方内部团队最佳实践!
前端·后端·程序员
开开心心就好24 分钟前
文档格式转换软件 一键Word转PDF
开发语言·前端·数据库·pdf·c#·word
袁煦丞1 小时前
Redis内存闪电侠:cpolar内网穿透第614个成功挑战
前端·程序员·远程工作
BillKu1 小时前
Vue3组件加载顺序
前端·javascript·vue.js
IT_陈寒1 小时前
Python性能优化必知必会:7个让代码快3倍的底层技巧与实战案例
前端·人工智能·后端
暖木生晖1 小时前
引入资源即针对于不同的屏幕尺寸,调用不同的css文件
前端·css·媒体查询
袁煦丞2 小时前
DS file文件管家远程自由:cpolar内网穿透实验室第492个成功挑战
前端·程序员·远程工作
用户013741284372 小时前
九个鲜为人知却极具威力的 CSS 功能:提升前端开发体验的隐藏技巧
前端
永远不打烊2 小时前
Window环境 WebRTC demo 运行
前端