confetti animation

This commit is contained in:
2026-03-03 12:15:50 +01:00
parent 77fa21b572
commit 88275c4ae6
16 changed files with 401 additions and 298 deletions

View File

@@ -15,3 +15,4 @@ export 'src/containers/section_container.dart';
export 'src/containers/footer_container.dart';
export 'src/rows/editable_row.dart';
export 'src/loading/app_loading_indicator.dart';
export 'src/confetti/confetti_overlay.dart';

View File

@@ -0,0 +1,91 @@
import 'dart:math';
import 'package:confetti/confetti.dart';
import 'package:flutter/material.dart';
class ConfettiOverlay extends StatefulWidget {
final bool play;
final Widget child;
final VoidCallback? onPlayed;
final Duration duration;
final List<Color> colors;
const ConfettiOverlay({
super.key,
required this.play,
required this.child,
this.onPlayed,
this.duration = const Duration(seconds: 3),
this.colors = const [
Color(0xFFFF69B4),
Color(0xFF4169E1),
Color(0xFFFF8C00),
Color(0xFF8A2BE2),
Color(0xFFFFD700),
],
});
@override
State<ConfettiOverlay> createState() => _ConfettiOverlayState();
}
class _ConfettiOverlayState extends State<ConfettiOverlay> {
late final ConfettiController _controller;
@override
void initState() {
super.initState();
_controller = ConfettiController(duration: widget.duration);
if (widget.play) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_controller.play();
widget.onPlayed?.call();
});
}
}
@override
void didUpdateWidget(covariant ConfettiOverlay oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.play && !oldWidget.play) {
_controller.play();
if (widget.onPlayed != null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
widget.onPlayed!();
});
}
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
widget.child,
Align(
alignment: Alignment.topCenter,
child: ConfettiWidget(
confettiController: _controller,
blastDirectionality: BlastDirectionality.explosive,
gravity: 0.1,
numberOfParticles: 10,
emissionFrequency: 0.2,
colors: widget.colors,
createParticlePath: (size) {
final random = Random();
final w = 10.0 + random.nextDouble() * 5.0;
final h = 5.0 + random.nextDouble() * 2.5;
return Path()..addRect(Rect.fromLTWH(0, 0, w, h));
},
),
),
],
);
}
}

View File

@@ -21,6 +21,7 @@ dependencies:
path: ../../packages/fonts
top_snackbar_flutter: ^3.3.0
lottie: ^3.3.1
confetti: ^0.7.0
dev_dependencies:
flutter_test: