import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import '../theme/app_colors.dart'; import '../widgets/animated_gradient_background.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @override State createState() => _HomePageState(); } class _HomePageState extends State with TickerProviderStateMixin { late AnimationController _mascotController; late Animation _mascotAnimation; late AnimationController _shineController; @override void initState() { super.initState(); // Mascot floating animation _mascotController = AnimationController( duration: const Duration(seconds: 4), vsync: this, )..repeat(reverse: true); _mascotAnimation = Tween(begin: -10, end: 10).animate( CurvedAnimation(parent: _mascotController, curve: Curves.easeInOut), ); // Shine sweep animation for connect button _shineController = AnimationController( duration: const Duration(seconds: 4), vsync: this, )..repeat(); } @override void dispose() { _mascotController.dispose(); _shineController.dispose(); super.dispose(); } void _handleConnect() { context.go('/bluetooth'); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: Stack( children: [ // Gradient Background _buildGradientBackground(), SafeArea( child: Column( children: [ // Header (Logo) _buildHeader(), // Main Content (Mascot) Expanded(child: _buildBody()), // Footer (Button) _buildFooter(), ], ), ), ], ), ); } Widget _buildGradientBackground() { return const AnimatedGradientBackground(); } Widget _buildHeader() { return Container( padding: const EdgeInsets.only(top: 32), alignment: Alignment.center, child: Text( 'Airhub', // Use Press Start 2P pixel font per HTML CSS style: GoogleFonts.pressStart2p( fontSize: 28, color: const Color(0xFF6366F1), // 靛蓝 letterSpacing: 2, shadows: const [ Shadow( color: Color(0x30A78BFA), offset: Offset(1, 1), blurRadius: 0, ), Shadow( color: Color(0x1AA78BFA), offset: Offset(2, 2), blurRadius: 0, ), ], ), ), ); } Widget _buildBody() { return Center( child: AnimatedBuilder( animation: _mascotAnimation, builder: (context, child) { return Transform.translate( offset: Offset(0, _mascotAnimation.value), child: child, ); }, child: Container( // Glow effect behind mascot decoration: BoxDecoration( shape: BoxShape.circle, boxShadow: [ BoxShadow( color: const Color(0xFF8B5CF6).withOpacity(0.15), blurRadius: 40, spreadRadius: 10, ), ], ), child: Transform.translate( offset: const Offset(16, 0), // HTML: translateX(5%) ≈ 16px on 320 child: Image.asset( 'assets/www/mascot_transparent.png', width: 320, // HTML: min(320px, 75vw) fit: BoxFit.contain, errorBuilder: (_, __, ___) => const Icon(Icons.adb, size: 200, color: Colors.grey), ), ), ), ), ); } Widget _buildFooter() { return Container( padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 56), child: Container( height: 58, // HTML: height: 58px constraints: const BoxConstraints(maxWidth: 300), // HTML: width: min(300px, 82vw) decoration: BoxDecoration( borderRadius: BorderRadius.circular(29), // HTML: border-radius: 29px gradient: AppColors.btnPrimaryGradient, // 5-layer box-shadow per HTML CSS --btn-primary-glow boxShadow: [ // 0 0 15px rgba(34, 211, 238, 0.35) - cyan outer glow BoxShadow( color: const Color(0xFF22D3EE).withOpacity(0.35), offset: Offset.zero, blurRadius: 15, ), // 0 0 30px rgba(99, 102, 241, 0.25) - indigo wider glow BoxShadow( color: const Color(0xFF6366F1).withOpacity(0.25), offset: Offset.zero, blurRadius: 30, ), // 0 6px 20px rgba(99, 102, 241, 0.4) - bottom shadow BoxShadow( color: const Color(0xFF6366F1).withOpacity(0.4), offset: const Offset(0, 6), blurRadius: 20, ), ], ), child: Stack( children: [ // Shine overlay (top half gradient) Positioned.fill( child: ClipRRect( borderRadius: BorderRadius.circular(29), child: DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.white.withOpacity(0.15), Colors.transparent, ], stops: const [0.0, 0.5], ), ), ), ), ), // Sweep shine animation (btn-shine from HTML) Positioned.fill( child: ClipRRect( borderRadius: BorderRadius.circular(29), child: AnimatedBuilder( animation: _shineController, builder: (context, child) { return Transform.translate( offset: Offset( (_shineController.value * 2 - 1) * 200, 0, ), child: child, ); }, child: Container( width: 120, decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.transparent, Colors.white.withOpacity(0.10), Colors.transparent, ], stops: const [0.0, 0.5, 1.0], ), ), ), ), ), ), // Button content Material( color: Colors.transparent, elevation: 0, child: InkWell( onTap: _handleConnect, borderRadius: BorderRadius.circular(29), child: Center( child: Text( '立即连接', style: GoogleFonts.dmSans( fontSize: 17, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: 0.5, ), ), ), ), ), ], ), ), ); } }