enaklo-flutter/lib/common/painter/wheel_painter.dart
2025-09-04 18:08:34 +07:00

185 lines
5.5 KiB
Dart

import 'dart:math' as math;
import 'package:flutter/material.dart';
import '../../presentation/pages/mini_games/ferris_wheel/data/model.dart';
import '../theme/theme.dart';
class WheelPainter extends CustomPainter {
final List<WheelSection> sections;
WheelPainter({required this.sections});
@override
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
final radius = size.width / 2;
final sectionAngle = 2 * math.pi / sections.length;
// Draw outer white border
final outerBorderPaint = Paint()
..color = Colors.white
..style = PaintingStyle.fill;
canvas.drawCircle(center, radius, outerBorderPaint);
// Draw blue border ring
final blueBorderPaint = Paint()
..color = const Color(0xFF3B82F6)
..style = PaintingStyle.fill;
canvas.drawCircle(center, radius - 8, blueBorderPaint);
// Draw inner white circle
final innerWhitePaint = Paint()
..color = Colors.white
..style = PaintingStyle.fill;
canvas.drawCircle(center, radius - 20, innerWhitePaint);
// Draw sections
for (int i = 0; i < sections.length; i++) {
final startAngle = i * sectionAngle - math.pi / 2;
// Section background
final sectionPaint = Paint()
..color = sections[i].color
..style = PaintingStyle.fill;
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius - 22),
startAngle,
sectionAngle,
true,
sectionPaint,
);
// Draw icon in each section
final iconAngle = startAngle + sectionAngle / 2;
final iconPosition = Offset(
center.dx + (radius - 60) * math.cos(iconAngle),
center.dy + (radius - 60) * math.sin(iconAngle),
);
// Draw icon background circle
final iconBgPaint = Paint()
..color = Colors.white
..style = PaintingStyle.fill;
canvas.drawCircle(iconPosition, 16, iconBgPaint);
// Save canvas state for icon drawing
canvas.save();
canvas.translate(iconPosition.dx, iconPosition.dy);
// Draw icon using TextPainter to simulate Icon widget
final iconText = _getIconText(sections[i].icon);
final iconTextPainter = TextPainter(
text: TextSpan(
text: iconText,
style: TextStyle(
fontFamily: 'MaterialIcons',
fontSize: 20,
color: sections[i].color,
fontWeight: FontWeight.normal,
),
),
textDirection: TextDirection.ltr,
);
iconTextPainter.layout();
iconTextPainter.paint(
canvas,
Offset(-iconTextPainter.width / 2, -iconTextPainter.height / 2),
);
canvas.restore();
// Draw prize text
final textAngle = startAngle + sectionAngle / 2;
final textPosition = Offset(
center.dx + (radius - 100) * math.cos(textAngle),
center.dy + (radius - 100) * math.sin(textAngle),
);
// Save canvas state for text rotation
canvas.save();
canvas.translate(textPosition.dx, textPosition.dy);
canvas.rotate(textAngle + math.pi / 2);
final textPainter = TextPainter(
text: TextSpan(
text: sections[i].prize,
style: const TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.bold,
),
),
textDirection: TextDirection.ltr,
);
textPainter.layout();
textPainter.paint(
canvas,
Offset(-textPainter.width / 2, -textPainter.height / 2),
);
canvas.restore();
}
// Draw white dots around the outer edge
final dotPaint = Paint()
..color = Colors.white
..style = PaintingStyle.fill;
for (int i = 0; i < 24; i++) {
final dotAngle = (2 * math.pi / 24) * i;
final dotPosition = Offset(
center.dx + (radius - 14) * math.cos(dotAngle),
center.dy + (radius - 14) * math.sin(dotAngle),
);
canvas.drawCircle(dotPosition, 3, dotPaint);
}
// Draw section dividers
final dividerPaint = Paint()
..color = AppColor.white
..style = PaintingStyle.stroke
..strokeWidth = 2;
for (int i = 0; i < sections.length; i++) {
final angle = i * sectionAngle - math.pi / 2;
final lineStart = Offset(
center.dx + (radius - 130) * math.cos(angle),
center.dy + (radius - 130) * math.sin(angle),
);
final lineEnd = Offset(
center.dx + (radius - 22) * math.cos(angle),
center.dy + (radius - 22) * math.sin(angle),
);
canvas.drawLine(lineStart, lineEnd, dividerPaint);
}
}
String _getIconText(IconData icon) {
// Convert IconData to Unicode string for drawing
switch (icon.codePoint) {
case 0xe8f4: // Icons.visibility
return String.fromCharCode(0xe8f4);
case 0xe8f5: // Icons.visibility_off
return String.fromCharCode(0xe8f5);
case 0xe850: // Icons.account_balance_wallet
return String.fromCharCode(0xe850);
case 0xe151: // Icons.card_giftcard
return String.fromCharCode(0xe151);
case 0xe5d5: // Icons.refresh
return String.fromCharCode(0xe5d5);
case 0xe263: // Icons.attach_money
return String.fromCharCode(0xe263);
case 0xe8a1: // Icons.redeem
return String.fromCharCode(0xe8a1);
case 0xe57d: // Icons.monetization_on
return String.fromCharCode(0xe57d);
default:
return String.fromCharCode(0xe87c); // Default star icon
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}