import 'dart:math' as math; import 'package:be_happy/presentation/event/spalsh_event.dart'; import 'package:be_happy/presentation/viewmodel/splash_bloc.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class SplashScreen extends StatefulWidget { const SplashScreen({super.key}); @override State createState() => _SplashScreenState(); } class _SplashScreenState extends State with SingleTickerProviderStateMixin { late final AnimationController _controller; // Фаза 1: Заполнение цветом слева направо (0.0 -> 0.5) late final Animation _fillProgress; // Фаза 2: Укатывание вправо (0.6 -> 1.0) late final Animation _rollTranslation; late final Animation _rollRotation; // Уменьшенный размер логотипа по вашему запросу static const double logoSize = 130; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 3000), ); _fillProgress = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation( parent: _controller, curve: const Interval(0.0, 0.5, curve: Curves.easeInOut), ), ); _rollTranslation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation( parent: _controller, curve: const Interval(0.6, 1.0, curve: Curves.easeInCubic), ), ); _rollRotation = Tween(begin: 0.0, end: 2 * math.pi).animate( CurvedAnimation( parent: _controller, curve: const Interval(0.6, 1.0, curve: Curves.easeIn), ), ); // Добавляем задержку перед стартом, чтобы пользователь успел увидеть экран WidgetsBinding.instance.addPostFrameCallback((_) async { if (!mounted) return; // Ждем 500мс после того, как первый кадр отрисовался await Future.delayed(const Duration(milliseconds: 500)); if (!mounted) return; // Запускаем анимацию _controller.forward().then((_) { if (!mounted) return; context.read().add(AuthCheckRequested()); }); }); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final double screenWidth = MediaQuery.of(context).size.width; final double endTranslation = screenWidth / 2 + logoSize; return Scaffold( body: Stack( children: [ Positioned.fill( child: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFF293A69), Color(0xFF202741), ], ), ), ), ), // 2. Волна Positioned( top: 0, left: 0, right: 0, child: Image.asset( 'assets/wave.png', fit: BoxFit.contain, ), ), Positioned( bottom: 0, left: 0, right: 0, child: Image.asset( 'assets/splash_map.png', fit: BoxFit.contain, ), ), Center( child: AnimatedBuilder( animation: _controller, builder: (context, child) { final double translationX = _rollTranslation.value * endTranslation; return Transform( transform: Matrix4.translationValues(translationX, 0, 0) ..rotateZ(_rollRotation.value), alignment: Alignment.center, // Используем ShaderMask для эффекта заполнения/проявления child: ShaderMask( shaderCallback: (bounds) { return LinearGradient( begin: Alignment.centerLeft, end: Alignment.centerRight, // Используем _fillProgress для сдвига жесткой границы градиента colors: const [Colors.white, Colors.transparent], stops: [_fillProgress.value, _fillProgress.value], ).createShader(bounds); }, blendMode: BlendMode.dstIn, // Оставляет только ту часть логотипа, где градиент белый child: Image.asset( 'assets/splash_logo.png', width: logoSize, height: logoSize, fit: BoxFit.contain, ), ), ); }, ), ), // 5. Версия приложения Positioned( left: 0, right: 0, bottom: 24, child: Text( 'Версия приложения 1.0', textAlign: TextAlign.center, style: TextStyle( color: Colors.white.withOpacity(0.6), fontSize: 12, fontWeight: FontWeight.w300, letterSpacing: 0.5, ), ), ), ], ), ); } }