Initial commit — DLS lab-app Flutter project
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
|
||||
/// Animated floating blob background used on auth screens.
|
||||
/// [bright] = true → white blobs (for dark/gradient backgrounds).
|
||||
/// [bright] = false → primary/accent blobs (for light backgrounds).
|
||||
class AnimatedAuthBg extends StatefulWidget {
|
||||
const AnimatedAuthBg({super.key, this.bright = false});
|
||||
final bool bright;
|
||||
|
||||
@override
|
||||
State<AnimatedAuthBg> createState() => _AnimatedAuthBgState();
|
||||
}
|
||||
|
||||
class _AnimatedAuthBgState extends State<AnimatedAuthBg>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _ctrl;
|
||||
late Animation<double> _anim;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_ctrl = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(seconds: 8),
|
||||
)..repeat(reverse: true);
|
||||
_anim = CurvedAnimation(parent: _ctrl, curve: Curves.easeInOut);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_ctrl.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Color _blob(double alpha) => widget.bright
|
||||
? Colors.white.withValues(alpha: alpha * 1.5)
|
||||
: AppColors.primary.withValues(alpha: alpha);
|
||||
|
||||
Color _blobAccent(double alpha) => widget.bright
|
||||
? Colors.white.withValues(alpha: alpha * 1.2)
|
||||
: AppColors.accent.withValues(alpha: alpha);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: _anim,
|
||||
builder: (_, __) {
|
||||
final t = _anim.value;
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: -80 + t * 30,
|
||||
left: -60 + t * 20,
|
||||
child: AuthBlob(size: 300, color: _blob(0.08)),
|
||||
),
|
||||
Positioned(
|
||||
top: 200 - t * 40,
|
||||
right: -100 + t * 25,
|
||||
child: AuthBlob(size: 250, color: _blobAccent(0.06)),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 100 + t * 30,
|
||||
left: 50 - t * 15,
|
||||
child: AuthBlob(size: 200, color: _blob(0.05)),
|
||||
),
|
||||
Positioned(
|
||||
bottom: -50 + t * 20,
|
||||
right: -50 + t * 10,
|
||||
child: AuthBlob(size: 280, color: _blobAccent(0.07)),
|
||||
),
|
||||
Positioned(
|
||||
top: 350 + t * 25,
|
||||
left: 80 + t * 20,
|
||||
child: AuthBlob(size: 160, color: _blob(0.04)),
|
||||
),
|
||||
Positioned(
|
||||
top: -40 - t * 10,
|
||||
left: 120 + t * 30,
|
||||
child: AuthBlob(size: 180, color: _blobAccent(0.05)),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple solid circle used as a background blob.
|
||||
class AuthBlob extends StatelessWidget {
|
||||
const AuthBlob({super.key, required this.size, required this.color});
|
||||
|
||||
final double size;
|
||||
final Color color;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: size,
|
||||
height: size,
|
||||
decoration: BoxDecoration(shape: BoxShape.circle, color: color),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user