flutter_glitter_effect 1.0.1
flutter_glitter_effect: ^1.0.1 copied to clipboard
description: A Flutter package for creating customizable glitter effects.
example/lib/main.dart
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Mouse Cursor Glitter Effect',
debugShowCheckedModeBanner: false,
theme: ThemeData.dark(),
home: const GlitterScreen(
numberOfParticles: 10,
speedOfParticles: 3.0,
width: double.infinity,
height: double.infinity,
particleColors: [Colors.red, Colors.grey, Colors.greenAccent],
isRandomColor: true,
particleShape: ParticleShape.circle,
particleLifespan: 2.0,
applyGravity: false,
initialBurst: 10,
trailLength: 5,
),
);
}
}
enum ParticleShape { circle, square, triangle, all }
class GlitterScreen extends StatefulWidget {
final int numberOfParticles;
final double speedOfParticles;
final double width;
final double height;
final List<Color> particleColors;
final bool isRandomColor;
final ParticleShape particleShape;
final double particleLifespan;
final bool applyGravity;
final int initialBurst;
final int trailLength;
const GlitterScreen({
super.key,
this.numberOfParticles = 5,
this.speedOfParticles = 3.0,
this.width = double.infinity,
this.height = double.infinity,
this.particleColors = const [Colors.red, Colors.green, Colors.blue],
this.isRandomColor = true,
this.particleShape = ParticleShape.circle,
this.particleLifespan = 2.0,
this.applyGravity = false,
this.initialBurst = 10,
this.trailLength = 5,
}) : assert(numberOfParticles <= 10, 'numberOfParticles must not exceed 10'),
assert(
speedOfParticles <= 20.0, 'speedOfParticles must not exceed 20.0');
@override
State<GlitterScreen> createState() => _GlitterScreenState();
}
class _GlitterScreenState extends State<GlitterScreen> {
List<Glitter> glitters = [];
Timer? _timer;
@override
void initState() {
super.initState();
_timer = Timer.periodic(const Duration(milliseconds: 30), (timer) {
setState(() {
for (var glitter in glitters) {
glitter.update(widget.applyGravity);
}
glitters.removeWhere((glitter) => glitter.size <= 0.2);
});
});
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onPanUpdate: (details) {
setState(() {
final x = details.localPosition.dx;
final y = details.localPosition.dy;
createGlitter(x, y);
});
},
onPanStart: (details) {
setState(() {
final x = details.localPosition.dx;
final y = details.localPosition.dy;
createInitialBurst(x, y);
});
},
child: CustomPaint(
painter: GlitterPainter(glitters, widget.particleShape),
size: Size(widget.width, widget.height),
),
),
);
}
void createGlitter(double x, double y) {
final random = Random();
for (int i = 0; i < widget.numberOfParticles; i++) {
glitters.add(Glitter(
x,
y,
random,
widget.speedOfParticles,
widget.particleColors,
widget.isRandomColor,
widget.particleLifespan,
));
}
}
void createInitialBurst(double x, double y) {
final random = Random();
for (int i = 0; i < widget.initialBurst; i++) {
glitters.add(Glitter(
x,
y,
random,
widget.speedOfParticles,
widget.particleColors,
widget.isRandomColor,
widget.particleLifespan,
));
}
}
}
class GlitterPainter extends CustomPainter {
final List<Glitter> glitters;
final ParticleShape particleShape;
GlitterPainter(this.glitters, this.particleShape);
@override
void paint(Canvas canvas, Size size) {
for (var glitter in glitters) {
glitter.draw(canvas, particleShape);
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
class Glitter {
double x;
double y;
double size;
double speedX;
double speedY;
Color color;
double lifespan;
Glitter(
this.x,
this.y,
Random random,
double speed,
List<Color> colors,
bool isRandomColor,
this.lifespan,
) : size = random.nextDouble() * 5 + 2,
speedX = random.nextDouble() * speed - speed / 2,
speedY = random.nextDouble() * speed - speed / 2,
color = isRandomColor
? Color.fromRGBO(
random.nextInt(256),
random.nextInt(256),
random.nextInt(256),
random.nextDouble(),
)
: colors[random.nextInt(colors.length)];
void update(bool applyGravity) {
x += speedX;
y += speedY;
if (applyGravity) {
speedY += 0.1;
}
if (size > 0.2) size -= 0.1;
}
void draw(Canvas canvas, ParticleShape shape) {
final paint = Paint()..color = color;
if (shape == ParticleShape.circle) {
canvas.drawCircle(Offset(x, y), size, paint);
} else if (shape == ParticleShape.square) {
canvas.drawRect(
Rect.fromCenter(center: Offset(x, y), width: size, height: size),
paint);
} else if (shape == ParticleShape.triangle) {
final path = Path()
..moveTo(x, y - size)
..lineTo(x - size, y + size)
..lineTo(x + size, y + size)
..close();
canvas.drawPath(path, paint);
} else if (shape == ParticleShape.all) {
canvas.drawCircle(Offset(x, y), size, paint);
canvas.drawRect(
Rect.fromCenter(center: Offset(x, y), width: size, height: size),
paint);
final path = Path()
..moveTo(x, y - size)
..lineTo(x - size, y + size)
..lineTo(x + size, y + size)
..close();
canvas.drawPath(path, paint);
}
}
}