draw updates
This commit is contained in:
parent
b1ecd70f8a
commit
ac9a0389d1
|
|
@ -569,284 +569,195 @@ class _SlotMachineDrawAnimationState extends State<SlotMachineDrawAnimation>
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final winnerName = _winnerId != null
|
||||||
|
? widget.members.firstWhere((m) => m['id'] == _winnerId)['name']
|
||||||
|
: null;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
width: 300.w,
|
width: 320.w,
|
||||||
height: 520.h,
|
height: 520.h,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
// Title
|
|
||||||
Text(
|
|
||||||
'Slot Machine Draw',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 20.sp,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.orange.shade700,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 20.h),
|
|
||||||
|
|
||||||
// Pointer/Indicator
|
|
||||||
Container(
|
|
||||||
width: 280.w,
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
Icons.keyboard_arrow_down,
|
|
||||||
color: Colors.red.shade600,
|
|
||||||
size: 30.w,
|
|
||||||
),
|
|
||||||
SizedBox(width: 8.w),
|
|
||||||
Text(
|
|
||||||
_isAnimating ? 'Selecting...' : 'Winner!',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14.sp,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: _isAnimating ? Colors.orange.shade600 : Colors.green.shade600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 8.w),
|
|
||||||
Icon(
|
|
||||||
Icons.keyboard_arrow_down,
|
|
||||||
color: Colors.red.shade600,
|
|
||||||
size: 30.w,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 10.h),
|
|
||||||
|
|
||||||
// Slot Machine Display
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 280.w,
|
width: double.infinity,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.grey.shade800,
|
gradient: LinearGradient(
|
||||||
borderRadius: BorderRadius.circular(16.r),
|
colors: [
|
||||||
|
Colors.grey.shade900,
|
||||||
|
Colors.grey.shade800,
|
||||||
|
],
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(20.r),
|
||||||
border: Border.all(color: Colors.orange.shade400, width: 3.w),
|
border: Border.all(color: Colors.orange.shade400, width: 3.w),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: Colors.black.withOpacity(0.3),
|
color: Colors.black.withOpacity(0.35),
|
||||||
blurRadius: 15.r,
|
blurRadius: 18.r,
|
||||||
offset: Offset(0, 8.h),
|
offset: Offset(0, 10.h),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Container(
|
||||||
children: [
|
margin: EdgeInsets.all(18.w),
|
||||||
// Slot Windows
|
decoration: BoxDecoration(
|
||||||
Expanded(
|
color: Colors.black,
|
||||||
child: Container(
|
borderRadius: BorderRadius.circular(12.r),
|
||||||
margin: EdgeInsets.all(16.w),
|
),
|
||||||
decoration: BoxDecoration(
|
child: Stack(
|
||||||
color: Colors.black,
|
children: [
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
AnimatedBuilder(
|
||||||
),
|
animation: _slotAnimation,
|
||||||
child: Stack(
|
builder: (context, child) {
|
||||||
children: [
|
return Column(
|
||||||
// Animated names
|
children: List.generate(7, (index) {
|
||||||
AnimatedBuilder(
|
final displayIndex = index < _displayNames.length ? index : 0;
|
||||||
animation: _slotAnimation,
|
final name = _displayNames[displayIndex];
|
||||||
builder: (context, child) {
|
final isWinner = _isComplete && index == 3;
|
||||||
return Column(
|
final isCenterHighlight = _isAnimating && index == 3;
|
||||||
children: List.generate(7, (index) {
|
|
||||||
final displayIndex = index < _displayNames.length ? index : 0;
|
return Expanded(
|
||||||
final name = _displayNames[displayIndex];
|
child: AnimatedBuilder(
|
||||||
final isWinner = _isComplete && index == 3; // Center position (middle of 7)
|
animation: _pulseAnimation,
|
||||||
final isCenterHighlight = _isAnimating && index == 3; // Always highlight center
|
builder: (context, child) {
|
||||||
|
final double scale = isWinner || isCenterHighlight ? 1.08 : 1.0;
|
||||||
return Expanded(
|
final double fontSize = isWinner
|
||||||
child: AnimatedBuilder(
|
? 24.sp
|
||||||
animation: _pulseAnimation,
|
: isCenterHighlight
|
||||||
builder: (context, child) {
|
? 20.sp
|
||||||
return AnimatedContainer(
|
: 18.sp;
|
||||||
duration: const Duration(milliseconds: 200),
|
final FontWeight weight = isWinner
|
||||||
curve: Curves.easeInOut,
|
? FontWeight.w900
|
||||||
transform: Matrix4.identity()
|
: isCenterHighlight
|
||||||
..scale(isCenterHighlight || isWinner ? 1.05 : 1.0),
|
? FontWeight.w800
|
||||||
child: Container(
|
: FontWeight.w700;
|
||||||
width: double.infinity,
|
final List<Color> colors = isWinner
|
||||||
margin: EdgeInsets.symmetric(vertical: 2.h, horizontal: 4.w),
|
? [Colors.green.shade500, Colors.green.shade600]
|
||||||
decoration: BoxDecoration(
|
: isCenterHighlight
|
||||||
gradient: isWinner
|
? [Colors.deepPurple.shade500, Colors.deepPurple.shade700]
|
||||||
? LinearGradient(
|
: [Colors.blueGrey.shade700, Colors.blueGrey.shade900];
|
||||||
colors: [
|
|
||||||
Colors.green.shade600,
|
return AnimatedContainer(
|
||||||
Colors.green.shade700,
|
duration: const Duration(milliseconds: 220),
|
||||||
],
|
curve: Curves.easeInOut,
|
||||||
)
|
transform: Matrix4.identity()..scale(scale),
|
||||||
: isCenterHighlight
|
child: Container(
|
||||||
? LinearGradient(
|
width: double.infinity,
|
||||||
colors: [
|
margin: EdgeInsets.symmetric(
|
||||||
Colors.orange.shade600,
|
vertical: 6.h,
|
||||||
Colors.red.shade600,
|
horizontal: 12.w,
|
||||||
],
|
),
|
||||||
)
|
decoration: BoxDecoration(
|
||||||
: LinearGradient(
|
gradient: LinearGradient(
|
||||||
colors: [
|
colors: colors,
|
||||||
Colors.blue.shade700,
|
begin: Alignment.topLeft,
|
||||||
Colors.blue.shade800,
|
end: Alignment.bottomRight,
|
||||||
],
|
),
|
||||||
),
|
borderRadius: BorderRadius.circular(10.r),
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
border: Border.all(
|
||||||
border: Border.all(
|
color: Colors.white.withOpacity(isWinner || isCenterHighlight ? 0.7 : 0.15),
|
||||||
color: isWinner || isCenterHighlight
|
width: isWinner || isCenterHighlight ? 2.w : 1.w,
|
||||||
? Colors.white.withOpacity(0.6)
|
),
|
||||||
: Colors.white.withOpacity(0.1),
|
boxShadow: [
|
||||||
width: isWinner || isCenterHighlight ? 2.w : 1.w,
|
BoxShadow(
|
||||||
),
|
color: Colors.black.withOpacity(0.4),
|
||||||
boxShadow: isWinner
|
blurRadius: isWinner ? 14.r : 6.r,
|
||||||
? [
|
offset: Offset(0, 3.h),
|
||||||
BoxShadow(
|
|
||||||
color: Colors.green.shade300,
|
|
||||||
blurRadius: 12.r,
|
|
||||||
spreadRadius: 3.r,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
: isCenterHighlight
|
|
||||||
? [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.orange.shade300.withOpacity(0.6),
|
|
||||||
blurRadius: 8.r,
|
|
||||||
spreadRadius: 2.r,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withOpacity(0.3),
|
|
||||||
blurRadius: 4.r,
|
|
||||||
offset: Offset(0, 2.h),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
name.length > 15 ? '${name.substring(0, 15)}...' : name,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: isWinner || isCenterHighlight ? 16.sp : 13.sp,
|
|
||||||
fontWeight: isWinner || isCenterHighlight
|
|
||||||
? FontWeight.w900
|
|
||||||
: FontWeight.w600,
|
|
||||||
color: Colors.white,
|
|
||||||
letterSpacing: 0.5,
|
|
||||||
shadows: [
|
|
||||||
Shadow(
|
|
||||||
color: Colors.black.withOpacity(0.5),
|
|
||||||
blurRadius: 3.r,
|
|
||||||
offset: Offset(1, 1),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
],
|
||||||
},
|
),
|
||||||
),
|
child: Center(
|
||||||
);
|
child: Text(
|
||||||
}),
|
name.length > 22 ? '${name.substring(0, 22)}…' : name,
|
||||||
);
|
style: TextStyle(
|
||||||
},
|
fontSize: fontSize,
|
||||||
),
|
fontWeight: weight,
|
||||||
|
color: Colors.white,
|
||||||
// Winner highlight
|
letterSpacing: 0.6,
|
||||||
if (_isComplete)
|
shadows: [
|
||||||
Positioned(
|
Shadow(
|
||||||
top: 0,
|
color: Colors.black.withOpacity(0.5),
|
||||||
left: 0,
|
blurRadius: 4.r,
|
||||||
right: 0,
|
offset: Offset(1.5, 1.5),
|
||||||
child: Container(
|
),
|
||||||
height: 60.h,
|
],
|
||||||
decoration: BoxDecoration(
|
),
|
||||||
color: Colors.green.shade400.withOpacity(0.3),
|
textAlign: TextAlign.center,
|
||||||
borderRadius: BorderRadius.circular(4.r),
|
maxLines: 1,
|
||||||
),
|
overflow: TextOverflow.ellipsis,
|
||||||
child: Center(
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Icon(Icons.emoji_events, color: Colors.yellow, size: 24.w),
|
|
||||||
SizedBox(width: 8.w),
|
|
||||||
Text(
|
|
||||||
'WINNER!',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 18.sp,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.yellow,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (_isComplete)
|
||||||
|
Positioned(
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: Container(
|
||||||
|
height: 70.h,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.green.shade400.withOpacity(0.35),
|
||||||
|
borderRadius: BorderRadius.circular(6.r),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.emoji_events, color: Colors.yellowAccent, size: 26.w),
|
||||||
|
SizedBox(width: 10.w),
|
||||||
|
Text(
|
||||||
|
'WINNER',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20.sp,
|
||||||
|
fontWeight: FontWeight.w900,
|
||||||
|
color: Colors.yellowAccent,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
// Slot Machine Controls
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.all(16.w),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: 40.w,
|
|
||||||
height: 40.w,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.red.shade600,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
child: Icon(Icons.stop, color: Colors.white, size: 20.w),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
width: 40.w,
|
|
||||||
height: 40.w,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.green.shade600,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
child: Icon(Icons.play_arrow, color: Colors.white, size: 20.w),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
width: 40.w,
|
|
||||||
height: 40.w,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.blue.shade600,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
child: Icon(Icons.pause, color: Colors.white, size: 20.w),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
// Status
|
if (_isComplete && winnerName != null)
|
||||||
SizedBox(height: 20.h),
|
Container(
|
||||||
if (_isAnimating)
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.h),
|
||||||
Text(
|
decoration: BoxDecoration(
|
||||||
'Slot machine spinning...',
|
color: Colors.green.shade50,
|
||||||
style: TextStyle(
|
borderRadius: BorderRadius.circular(12.r),
|
||||||
fontSize: 16.sp,
|
|
||||||
color: Colors.orange.shade600,
|
|
||||||
),
|
),
|
||||||
)
|
child: Row(
|
||||||
else if (_isComplete)
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
Text(
|
children: [
|
||||||
'Winner: ${widget.members.firstWhere((m) => m['id'] == _winnerId)['name']}',
|
Icon(Icons.emoji_events, color: Colors.green.shade600, size: 20.w),
|
||||||
style: TextStyle(
|
SizedBox(width: 8.w),
|
||||||
fontSize: 16.sp,
|
Flexible(
|
||||||
color: Colors.green.shade600,
|
child: Text(
|
||||||
fontWeight: FontWeight.bold,
|
winnerName,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18.sp,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: Colors.green.shade700,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'animated_draw_wheel.dart';
|
|
||||||
import 'alternative_draw_animations.dart';
|
import 'alternative_draw_animations.dart';
|
||||||
import 'particle_draw_animation.dart';
|
|
||||||
|
|
||||||
enum DrawAnimationType {
|
|
||||||
spinningWheel,
|
|
||||||
cardFlip,
|
|
||||||
slotMachine,
|
|
||||||
numberRoulette,
|
|
||||||
particleSystem,
|
|
||||||
}
|
|
||||||
|
|
||||||
class DrawAnimationSelector extends StatefulWidget {
|
class DrawAnimationSelector extends StatefulWidget {
|
||||||
final List<Map<String, dynamic>> members;
|
final List<Map<String, dynamic>> members;
|
||||||
|
|
@ -35,28 +25,11 @@ class DrawAnimationSelector extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DrawAnimationSelectorState extends State<DrawAnimationSelector> {
|
class _DrawAnimationSelectorState extends State<DrawAnimationSelector> {
|
||||||
DrawAnimationType _selectedAnimation = DrawAnimationType.cardFlip;
|
|
||||||
bool _isDrawStarted = false;
|
bool _isDrawStarted = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// Auto-select best animation based on member count
|
|
||||||
_selectBestAnimation();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _selectBestAnimation() {
|
|
||||||
final memberCount = widget.members.length;
|
|
||||||
|
|
||||||
if (memberCount <= 8) {
|
|
||||||
_selectedAnimation = DrawAnimationType.spinningWheel;
|
|
||||||
} else if (memberCount <= 20) {
|
|
||||||
_selectedAnimation = DrawAnimationType.cardFlip;
|
|
||||||
} else if (memberCount <= 50) {
|
|
||||||
_selectedAnimation = DrawAnimationType.slotMachine;
|
|
||||||
} else {
|
|
||||||
_selectedAnimation = DrawAnimationType.particleSystem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startDraw() {
|
void _startDraw() {
|
||||||
|
|
@ -73,7 +46,7 @@ class _DrawAnimationSelectorState extends State<DrawAnimationSelector> {
|
||||||
|
|
||||||
Widget _buildAnimationSelector() {
|
Widget _buildAnimationSelector() {
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.all(20.w),
|
padding: EdgeInsets.all(24.w),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(16.r),
|
borderRadius: BorderRadius.circular(16.r),
|
||||||
|
|
@ -86,33 +59,58 @@ class _DrawAnimationSelectorState extends State<DrawAnimationSelector> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Container(
|
||||||
'Choose Draw Animation',
|
width: 72.w,
|
||||||
style: TextStyle(
|
height: 72.w,
|
||||||
fontSize: 20.sp,
|
decoration: BoxDecoration(
|
||||||
fontWeight: FontWeight.bold,
|
color: Colors.purple.shade50,
|
||||||
color: Colors.grey.shade800,
|
borderRadius: BorderRadius.circular(20.r),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
Icons.casino,
|
||||||
|
color: Colors.purple.shade600,
|
||||||
|
size: 36.w,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 16.h),
|
SizedBox(height: 16.h),
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
'Members: ${widget.members.length}',
|
'Slot Machine Draw',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 22.sp,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: Colors.grey.shade800,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
SizedBox(height: 12.h),
|
||||||
|
Text(
|
||||||
|
'Our signature animation for dramatic, high-energy winner reveals.',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14.sp,
|
fontSize: 14.sp,
|
||||||
color: Colors.grey.shade600,
|
color: Colors.grey.shade600,
|
||||||
|
height: 1.4,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.h),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.purple.shade50,
|
||||||
|
borderRadius: BorderRadius.circular(12.r),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Members in draw: ${widget.members.length}',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13.sp,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Colors.purple.shade600,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 20.h),
|
|
||||||
|
|
||||||
// Animation Options
|
|
||||||
...DrawAnimationType.values.map((type) => _buildAnimationOption(type)),
|
|
||||||
|
|
||||||
SizedBox(height: 24.h),
|
SizedBox(height: 24.h),
|
||||||
|
|
||||||
// Start Button
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
|
|
@ -131,7 +129,7 @@ class _DrawAnimationSelectorState extends State<DrawAnimationSelector> {
|
||||||
Icon(Icons.play_arrow, size: 20.w),
|
Icon(Icons.play_arrow, size: 20.w),
|
||||||
SizedBox(width: 8.w),
|
SizedBox(width: 8.w),
|
||||||
Text(
|
Text(
|
||||||
'Start ${_getAnimationName(_selectedAnimation)}',
|
'Start Slot Machine',
|
||||||
style: TextStyle(fontSize: 16.sp),
|
style: TextStyle(fontSize: 16.sp),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -143,221 +141,6 @@ class _DrawAnimationSelectorState extends State<DrawAnimationSelector> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAnimationOption(DrawAnimationType type) {
|
|
||||||
final isSelected = _selectedAnimation == type;
|
|
||||||
final isRecommended = _isRecommendedAnimation(type);
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
margin: EdgeInsets.only(bottom: 12.h),
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
setState(() {
|
|
||||||
_selectedAnimation = type;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
borderRadius: BorderRadius.circular(12.r),
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.all(16.w),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: isSelected ? Colors.purple.shade50 : Colors.grey.shade50,
|
|
||||||
borderRadius: BorderRadius.circular(12.r),
|
|
||||||
border: Border.all(
|
|
||||||
color: isSelected ? Colors.purple.shade300 : Colors.grey.shade300,
|
|
||||||
width: 2.w,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: 24.w,
|
|
||||||
height: 24.w,
|
|
||||||
margin: EdgeInsets.only(top: 2.h),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: isSelected ? Colors.purple.shade600 : Colors.grey.shade400,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
child: isSelected
|
|
||||||
? Icon(Icons.check, color: Colors.white, size: 16.w)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
SizedBox(width: 12.w),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
_getAnimationName(type),
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16.sp,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: isSelected ? Colors.purple.shade800 : Colors.grey.shade800,
|
|
||||||
),
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (isRecommended) ...[
|
|
||||||
SizedBox(width: 6.w),
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 2.h),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.green.shade100,
|
|
||||||
borderRadius: BorderRadius.circular(12.r),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
'Recommended',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10.sp,
|
|
||||||
color: Colors.green.shade700,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 6.h),
|
|
||||||
Text(
|
|
||||||
_getAnimationDescription(type),
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12.sp,
|
|
||||||
color: Colors.grey.shade600,
|
|
||||||
height: 1.3,
|
|
||||||
),
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 12.w),
|
|
||||||
Icon(
|
|
||||||
_getAnimationIcon(type),
|
|
||||||
color: isSelected ? Colors.purple.shade600 : Colors.grey.shade400,
|
|
||||||
size: 28.w,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _isRecommendedAnimation(DrawAnimationType type) {
|
|
||||||
final memberCount = widget.members.length;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case DrawAnimationType.spinningWheel:
|
|
||||||
return memberCount <= 8;
|
|
||||||
case DrawAnimationType.cardFlip:
|
|
||||||
return memberCount > 8 && memberCount <= 20;
|
|
||||||
case DrawAnimationType.slotMachine:
|
|
||||||
return memberCount > 20 && memberCount <= 50;
|
|
||||||
case DrawAnimationType.numberRoulette:
|
|
||||||
return memberCount > 20 && memberCount <= 100;
|
|
||||||
case DrawAnimationType.particleSystem:
|
|
||||||
return memberCount > 50;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String _getAnimationName(DrawAnimationType type) {
|
|
||||||
switch (type) {
|
|
||||||
case DrawAnimationType.spinningWheel:
|
|
||||||
return 'Spinning Wheel';
|
|
||||||
case DrawAnimationType.cardFlip:
|
|
||||||
return 'Card Flip';
|
|
||||||
case DrawAnimationType.slotMachine:
|
|
||||||
return 'Slot Machine';
|
|
||||||
case DrawAnimationType.numberRoulette:
|
|
||||||
return 'Number Roulette';
|
|
||||||
case DrawAnimationType.particleSystem:
|
|
||||||
return 'Particle System';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String _getAnimationDescription(DrawAnimationType type) {
|
|
||||||
switch (type) {
|
|
||||||
case DrawAnimationType.spinningWheel:
|
|
||||||
return 'Classic spinning wheel - Best for small groups (≤8 members)';
|
|
||||||
case DrawAnimationType.cardFlip:
|
|
||||||
return 'Cards flipping rapidly - Great for medium groups (9-20 members)';
|
|
||||||
case DrawAnimationType.slotMachine:
|
|
||||||
return 'Slot machine style - Perfect for large groups (21-50 members)';
|
|
||||||
case DrawAnimationType.numberRoulette:
|
|
||||||
return 'Number roulette wheel - Good for very large groups (21-100 members)';
|
|
||||||
case DrawAnimationType.particleSystem:
|
|
||||||
return 'Particle effects - Best for massive groups (50+ members)';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IconData _getAnimationIcon(DrawAnimationType type) {
|
|
||||||
switch (type) {
|
|
||||||
case DrawAnimationType.spinningWheel:
|
|
||||||
return Icons.casino;
|
|
||||||
case DrawAnimationType.cardFlip:
|
|
||||||
return Icons.style;
|
|
||||||
case DrawAnimationType.slotMachine:
|
|
||||||
return Icons.games;
|
|
||||||
case DrawAnimationType.numberRoulette:
|
|
||||||
return Icons.timeline;
|
|
||||||
case DrawAnimationType.particleSystem:
|
|
||||||
return Icons.auto_awesome;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildSelectedAnimation() {
|
|
||||||
switch (_selectedAnimation) {
|
|
||||||
case DrawAnimationType.spinningWheel:
|
|
||||||
return AnimatedDrawWheel(
|
|
||||||
members: widget.members,
|
|
||||||
onDrawComplete: widget.onDrawComplete,
|
|
||||||
serverSeed: widget.serverSeed,
|
|
||||||
clientSeed: widget.clientSeed,
|
|
||||||
nonce: widget.nonce,
|
|
||||||
);
|
|
||||||
case DrawAnimationType.cardFlip:
|
|
||||||
return CardFlipDrawAnimation(
|
|
||||||
members: widget.members,
|
|
||||||
onDrawComplete: widget.onDrawComplete,
|
|
||||||
serverSeed: widget.serverSeed,
|
|
||||||
clientSeed: widget.clientSeed,
|
|
||||||
nonce: widget.nonce,
|
|
||||||
animationDuration: widget.animationDuration,
|
|
||||||
);
|
|
||||||
case DrawAnimationType.slotMachine:
|
|
||||||
return SlotMachineDrawAnimation(
|
|
||||||
members: widget.members,
|
|
||||||
onDrawComplete: widget.onDrawComplete,
|
|
||||||
serverSeed: widget.serverSeed,
|
|
||||||
clientSeed: widget.clientSeed,
|
|
||||||
nonce: widget.nonce,
|
|
||||||
animationDuration: widget.animationDuration,
|
|
||||||
);
|
|
||||||
case DrawAnimationType.numberRoulette:
|
|
||||||
return NumberRouletteDrawAnimation(
|
|
||||||
members: widget.members,
|
|
||||||
onDrawComplete: widget.onDrawComplete,
|
|
||||||
serverSeed: widget.serverSeed,
|
|
||||||
clientSeed: widget.clientSeed,
|
|
||||||
nonce: widget.nonce,
|
|
||||||
animationDuration: widget.animationDuration,
|
|
||||||
);
|
|
||||||
case DrawAnimationType.particleSystem:
|
|
||||||
return ParticleDrawAnimation(
|
|
||||||
members: widget.members,
|
|
||||||
onDrawComplete: widget.onDrawComplete,
|
|
||||||
serverSeed: widget.serverSeed,
|
|
||||||
clientSeed: widget.clientSeed,
|
|
||||||
nonce: widget.nonce,
|
|
||||||
animationDuration: widget.animationDuration,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
|
|
@ -366,7 +149,14 @@ class _DrawAnimationSelectorState extends State<DrawAnimationSelector> {
|
||||||
children: [
|
children: [
|
||||||
if (!_isDrawStarted) _buildAnimationSelector(),
|
if (!_isDrawStarted) _buildAnimationSelector(),
|
||||||
if (_isDrawStarted) ...[
|
if (_isDrawStarted) ...[
|
||||||
_buildSelectedAnimation(),
|
SlotMachineDrawAnimation(
|
||||||
|
members: widget.members,
|
||||||
|
onDrawComplete: widget.onDrawComplete,
|
||||||
|
serverSeed: widget.serverSeed,
|
||||||
|
clientSeed: widget.clientSeed,
|
||||||
|
nonce: widget.nonce,
|
||||||
|
animationDuration: widget.animationDuration,
|
||||||
|
),
|
||||||
SizedBox(height: 20.h),
|
SizedBox(height: 20.h),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
|
@ -378,9 +168,20 @@ class _DrawAnimationSelectorState extends State<DrawAnimationSelector> {
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Row(
|
||||||
'Choose Different Animation',
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
style: TextStyle(fontSize: 14.sp),
|
children: [
|
||||||
|
Icon(Icons.refresh, size: 18.w, color: Colors.purple.shade600),
|
||||||
|
SizedBox(width: 6.w),
|
||||||
|
Text(
|
||||||
|
'Spin Again',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Colors.purple.shade600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue