import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app8/particle_widget.dart';
import 'package:simple_animations/simple_animations.dart';
import 'package:supercharged/supercharged.dart';
enum _ColorTween { color1, color2 }
main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("动画"),
),
body: Stack(
children: [
Positioned.fill(child: AnimatedBackground()),
Positioned.fill(child: ParticlesWidget(30))
],
),
),
);
}
}
class AnimatedBackground extends StatelessWidget {
@override
Widget build(BuildContext context) {
final tween = MultiTween<_ColorTween>()
..add(
_ColorTween.color1,
Color(0xffD38312).tweenTo(Colors.lightBlue.shade900),
3.seconds,
)
..add(
_ColorTween.color2,
Color(0xffA83279).tweenTo(Colors.blue.shade600),
3.seconds,
);
return MirrorAnimation<MultiTweenValues<_ColorTween>>(
tween: tween,
duration: tween.duration,
builder: (context, child, value) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
value.get<Color>(_ColorTween.color1),
value.get<Color>(_ColorTween.color2)
])),
);
},
);
}
}
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_app8/particle_model.dart';
import 'package:flutter_app8/particle_painter.dart';
import 'package:simple_animations/simple_animations.dart';
import 'package:supercharged/supercharged.dart';
class ParticlesWidget extends StatefulWidget {
final int numberOfParticles;
ParticlesWidget(this.numberOfParticles);
@override
_ParticlesWidgetState createState() => _ParticlesWidgetState();
}
class _ParticlesWidgetState extends State<ParticlesWidget> {
final Random random = Random();
final List<ParticleModel> particles = [];
@override
void initState() {
widget.numberOfParticles.times(() => particles.add(ParticleModel(random)));
super.initState();
}
@override
Widget build(BuildContext context) {
return LoopAnimation(
tween: ConstantTween(1),
builder: (context, child, _) {
_simulateParticles();
return CustomPaint(
painter: ParticlePainter(particles),
);
},
);
}
_simulateParticles() {
particles.forEach((particle) => particle.checkIfParticleNeedsToBeRestarted());
}
}
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:simple_animations/simple_animations.dart';
import 'package:supercharged/supercharged.dart';
enum ParticleOffsetProps { x, y }
class ParticleModel {
MultiTween<ParticleOffsetProps> tween;
double size;
Duration duration;
Duration startTime;
Random random;
ParticleModel(this.random) {
_restart();
_shuffle();
}
_restart() {
final startPosition = Offset(-0.2 + 1.4 * random.nextDouble(), 1.2);
final endPosition = Offset(-0.2 + 1.4 * random.nextDouble(), -0.2);
tween = MultiTween<ParticleOffsetProps>()
..add(ParticleOffsetProps.x, startPosition.dx.tweenTo(endPosition.dx))
..add(ParticleOffsetProps.y, startPosition.dy.tweenTo(endPosition.dy));
duration = 3000.milliseconds + random.nextInt(6000).milliseconds;
startTime = DateTime.now().duration();
size = 0.2 + random.nextDouble() * 0.4;
}
void _shuffle() {
startTime -= (this.random.nextDouble() * duration.inMilliseconds)
.round()
.milliseconds;
}
checkIfParticleNeedsToBeRestarted() {
if (progress() == 1.0) {
_restart();
}
}
double progress() {
return ((DateTime.now().duration() - startTime) / duration)
.clamp(0.0, 1.0)
.toDouble();
}
}
import 'package:flutter/material.dart';
import 'package:flutter_app8/particle_model.dart';
import 'package:simple_animations/simple_animations.dart';
class ParticlePainter extends CustomPainter {
List<ParticleModel> particles;
ParticlePainter(this.particles);
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = Colors.white.withAlpha(50);
particles.forEach((particle) {
final progress = particle.progress();
final MultiTweenValues<ParticleOffsetProps> animation =
particle.tween.transform(progress);
final position = Offset(
animation.get<double>(ParticleOffsetProps.x) * size.width,
animation.get<double>(ParticleOffsetProps.y) * size.height,
);
canvas.drawCircle(position, size.width * 0.2 * particle.size, paint);
});
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}