proxybuy-flutter/lib/widgets/animated_splash_screen.dart

184 lines
5.1 KiB
Dart

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:lba/res/colors.dart';
import 'package:flutter_svg/flutter_svg.dart';
import '../gen/assets.gen.dart';
class SplashScreen extends StatefulWidget {
final Widget nextScreen;
final Duration duration;
const SplashScreen({
super.key,
required this.nextScreen,
this.duration = const Duration(seconds: 6),
});
@override
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen>
with TickerProviderStateMixin {
late AnimationController _mainController;
late Animation<double> _backgroundAnimation;
late Animation<double> _particlesAnimation;
late Animation<double> _logoAnimation;
late Animation<double> _textAnimation;
@override
void initState() {
super.initState();
_mainController = AnimationController(
duration: const Duration(milliseconds: 4000),
vsync: this,
);
_backgroundAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _mainController,
curve: const Interval(0.0, 0.5, curve: Curves.easeInOut),
),
);
_particlesAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _mainController,
curve: const Interval(0.2, 0.7, curve: Curves.easeOut),
),
);
_logoAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _mainController,
curve: const Interval(0.5, 0.9, curve: Curves.elasticOut),
),
);
_textAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _mainController,
curve: const Interval(0.7, 1.0, curve: Curves.easeOut),
),
);
_mainController.forward();
Future.delayed(widget.duration, () {
if (mounted) {
Navigator.of(context).pushReplacement(
PageRouteBuilder(
pageBuilder: (_, __, ___) => widget.nextScreen,
transitionDuration: const Duration(milliseconds: 700),
transitionsBuilder: (_, animation, __, child) {
return FadeTransition(opacity: animation, child: child);
},
),
);
}
});
}
@override
void dispose() {
_mainController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: AnimatedBuilder(
animation: _mainController,
builder: (context, child) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color.lerp(
AppColors.scaffoldBackground,
AppColors.surface,
_backgroundAnimation.value,
)!,
Color.lerp(
AppColors.surface,
AppColors.scaffoldBackground,
_backgroundAnimation.value,
)!,
],
),
),
child: Stack(
children: [
for (int i = 0; i < 30; i++)
Particle(
animation: _particlesAnimation,
size: Random().nextDouble() * 5 + 2,
color: AppColors.textSecondary.withOpacity(
Random().nextDouble() * 0.3 + 0.1,
),
alignment: Alignment(
(Random().nextDouble() * 2 - 1) *
(2 - _particlesAnimation.value),
(Random().nextDouble() * 2 - 1) *
(2 - _particlesAnimation.value),
),
),
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Transform.scale(
scale: _logoAnimation.value,
child: SvgPicture.asset(
Assets.images.logo.path,
height: 140,
width: 140,
),
),
const SizedBox(height: 30),
],
),
),
],
),
);
},
),
);
}
}
class Particle extends StatelessWidget {
final Animation<double> animation;
final double size;
final Color color;
final Alignment alignment;
const Particle({
super.key,
required this.animation,
required this.size,
required this.color,
required this.alignment,
});
@override
Widget build(BuildContext context) {
return Align(
alignment: alignment,
child: Opacity(
opacity: animation.value,
child: Container(
width: size,
height: size,
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
),
),
);
}
}