animated_background.dart 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import 'package:flutter/material.dart';
  2. import 'dart:math' as math;
  3. import '../../utils/colors.dart';
  4. class AnimatedBackground extends StatefulWidget {
  5. final Widget child;
  6. final bool isZenMode;
  7. final Function()? onShake;
  8. const AnimatedBackground({
  9. super.key,
  10. required this.child,
  11. this.isZenMode = false,
  12. this.onShake,
  13. });
  14. @override
  15. State<AnimatedBackground> createState() => _AnimatedBackgroundState();
  16. }
  17. class _AnimatedBackgroundState extends State<AnimatedBackground>
  18. with TickerProviderStateMixin {
  19. late AnimationController _controller1;
  20. late AnimationController _controller2;
  21. late AnimationController _controller3;
  22. late AnimationController _shakeController;
  23. bool _isShaking = false;
  24. @override
  25. void initState() {
  26. super.initState();
  27. // Create multiple animation controllers for layered effects (optimized for performance)
  28. _controller1 = AnimationController(
  29. duration: const Duration(seconds: 60), // Slower animations for better performance
  30. vsync: this,
  31. )..repeat();
  32. _controller2 = AnimationController(
  33. duration: const Duration(seconds: 80), // Slower animations for better performance
  34. vsync: this,
  35. )..repeat();
  36. _controller3 = AnimationController(
  37. duration: const Duration(seconds: 100), // Much slower for better performance
  38. vsync: this,
  39. )..repeat();
  40. // Shake effect controller
  41. _shakeController = AnimationController(
  42. duration: const Duration(milliseconds: 800),
  43. vsync: this,
  44. );
  45. }
  46. @override
  47. void dispose() {
  48. _controller1.dispose();
  49. _controller2.dispose();
  50. _controller3.dispose();
  51. _shakeController.dispose();
  52. super.dispose();
  53. }
  54. void triggerShake() {
  55. if (!_isShaking) {
  56. _isShaking = true;
  57. _shakeController.forward().then((_) {
  58. _shakeController.reset();
  59. _isShaking = false;
  60. });
  61. widget.onShake?.call();
  62. }
  63. }
  64. @override
  65. Widget build(BuildContext context) {
  66. return Stack(
  67. children: [
  68. // Base background
  69. Container(
  70. decoration: const BoxDecoration(
  71. gradient: LinearGradient(
  72. begin: Alignment.topLeft,
  73. end: Alignment.bottomRight,
  74. colors: [
  75. ZenColors.appBackground,
  76. Color(0xFF0A0A0A),
  77. ],
  78. ),
  79. ),
  80. ),
  81. // Animated gradient layers (reduced to 2 for better performance)
  82. ...List.generate(2, (index) => _buildAnimatedLayer(index)),
  83. // Content overlay
  84. widget.child,
  85. ],
  86. );
  87. }
  88. Widget _buildAnimatedLayer(int layerIndex) {
  89. AnimationController controller;
  90. List<Color> colors;
  91. switch (layerIndex) {
  92. case 0:
  93. controller = _controller1;
  94. colors = widget.isZenMode
  95. ? [ZenColors.navyBlue.withValues(alpha: 0.3), Colors.transparent]
  96. : [ZenColors.uiElements.withValues(alpha: 0.2), Colors.transparent];
  97. break;
  98. case 1:
  99. controller = _controller2;
  100. colors = [ZenColors.red.withValues(alpha: 0.1), Colors.transparent];
  101. break;
  102. default:
  103. controller = _controller3;
  104. colors = [ZenColors.buttonBackground.withValues(alpha: 0.05), Colors.transparent];
  105. }
  106. return AnimatedBuilder(
  107. animation: Listenable.merge([controller, _shakeController]),
  108. builder: (context, child) {
  109. // Add shake effect
  110. double shakeIntensity = 0.0;
  111. if (_isShaking) {
  112. shakeIntensity = math.sin(_shakeController.value * math.pi * 8) *
  113. (1 - _shakeController.value) * 10; // Decay over time
  114. }
  115. return Transform.translate(
  116. offset: Offset(
  117. shakeIntensity * (math.Random().nextDouble() - 0.5) * 2,
  118. shakeIntensity * (math.Random().nextDouble() - 0.5) * 2,
  119. ),
  120. child: Transform.rotate(
  121. angle: controller.value * 2 * math.pi,
  122. child: Container(
  123. decoration: BoxDecoration(
  124. gradient: RadialGradient(
  125. center: Alignment(
  126. math.sin(controller.value * 2 * math.pi) * 0.5,
  127. math.cos(controller.value * 2 * math.pi) * 0.5,
  128. ),
  129. radius: 1.5 + math.sin(controller.value * math.pi) * 0.5 +
  130. (shakeIntensity * 0.1), // Shake affects radius too
  131. colors: colors,
  132. ),
  133. ),
  134. ),
  135. ),
  136. );
  137. },
  138. );
  139. }
  140. }