| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- import 'package:flutter/material.dart';
- import 'dart:math' as math;
- import '../../utils/colors.dart';
- import '../../utils/theme_notifier.dart';
- class AnimatedBackground extends StatefulWidget {
- final Widget child;
- final bool isZenMode;
- final Function()? onShake;
- const AnimatedBackground({
- super.key,
- required this.child,
- this.isZenMode = false,
- this.onShake,
- });
- @override
- State<AnimatedBackground> createState() => _AnimatedBackgroundState();
- }
- class _AnimatedBackgroundState extends State<AnimatedBackground>
- with TickerProviderStateMixin {
- late AnimationController _controller1;
- late AnimationController _controller2;
- late AnimationController _controller3;
- late AnimationController _shakeController;
-
- bool _isShaking = false;
- @override
- void initState() {
- super.initState();
-
- // Create multiple animation controllers for layered effects (optimized for performance)
- _controller1 = AnimationController(
- duration: const Duration(seconds: 60), // Slower animations for better performance
- vsync: this,
- )..repeat();
-
- _controller2 = AnimationController(
- duration: const Duration(seconds: 80), // Slower animations for better performance
- vsync: this,
- )..repeat();
-
- _controller3 = AnimationController(
- duration: const Duration(seconds: 100), // Much slower for better performance
- vsync: this,
- )..repeat();
-
- // Shake effect controller
- _shakeController = AnimationController(
- duration: const Duration(milliseconds: 800),
- vsync: this,
- );
- }
- @override
- void dispose() {
- _controller1.dispose();
- _controller2.dispose();
- _controller3.dispose();
- _shakeController.dispose();
- super.dispose();
- }
-
- void triggerShake() {
- if (!_isShaking) {
- _isShaking = true;
- _shakeController.forward().then((_) {
- _shakeController.reset();
- _isShaking = false;
- });
- widget.onShake?.call();
- }
- }
- @override
- Widget build(BuildContext context) {
- return ThemeAwareBuilder(
- builder: (context, theme) {
- return Stack(
- children: [
- // Base background
- Container(
- decoration: BoxDecoration(
- gradient: LinearGradient(
- begin: Alignment.topLeft,
- end: Alignment.bottomRight,
- colors: [
- ZenColors.currentAppBackground,
- ZenColors.currentSecondaryBackground,
- ],
- ),
- ),
- ),
-
- // Animated gradient layers (reduced to 2 for better performance)
- ...List.generate(2, (index) => _buildAnimatedLayer(index)),
-
- // Content overlay
- widget.child,
- ],
- );
- },
- );
- }
- Widget _buildAnimatedLayer(int layerIndex) {
- AnimationController controller;
- List<Color> colors;
-
- switch (layerIndex) {
- case 0:
- controller = _controller1;
- colors = widget.isZenMode
- ? ZenColors.zenModeColors
- : ZenColors.animationLayer1;
- break;
- case 1:
- controller = _controller2;
- colors = ZenColors.animationLayer2;
- break;
- default:
- controller = _controller3;
- colors = ZenColors.animationLayer3;
- }
- return AnimatedBuilder(
- animation: Listenable.merge([controller, _shakeController]),
- builder: (context, child) {
- // Add shake effect
- double shakeIntensity = 0.0;
- if (_isShaking) {
- shakeIntensity = math.sin(_shakeController.value * math.pi * 8) *
- (1 - _shakeController.value) * 10; // Decay over time
- }
-
- return Transform.translate(
- offset: Offset(
- shakeIntensity * (math.Random().nextDouble() - 0.5) * 2,
- shakeIntensity * (math.Random().nextDouble() - 0.5) * 2,
- ),
- child: Transform.rotate(
- angle: controller.value * 2 * math.pi,
- child: Container(
- decoration: BoxDecoration(
- gradient: RadialGradient(
- center: Alignment(
- math.sin(controller.value * 2 * math.pi) * 0.5,
- math.cos(controller.value * 2 * math.pi) * 0.5,
- ),
- radius: 1.5 + math.sin(controller.value * math.pi) * 0.5 +
- (shakeIntensity * 0.1), // Shake affects radius too
- colors: colors,
- ),
- ),
- ),
- ),
- );
- },
- );
- }
- }
|