This commit is contained in:
2026-08-08 10:57:54 +08:00
parent d0d48c1ffc
commit 604af909b0
184 changed files with 12521 additions and 12722 deletions
@@ -0,0 +1,95 @@
import 'package:flutter/material.dart';
import '../../../../data/local/models/models.dart';
/// Paints a standard 10-ring archery target face and optionally overlays
/// recorded [HitPoint]s. Coordinates use the normalized convention where
/// (0, 0) is the center and radius 1.0 is the outer scoring edge.
class TargetFacePainter extends CustomPainter {
TargetFacePainter({
this.hitPoints = const <HitPoint>[],
this.highlightIndex,
this.showAllHits = true,
this.hitColor = const Color(0xFF1A1A1A),
this.ringStrokeWidth = 1.0,
});
final List<HitPoint> hitPoints;
final int? highlightIndex;
final bool showAllHits;
final Color hitColor;
final double ringStrokeWidth;
// Ring colors from center outward: 10,9 gold | 8,7 red | 6,5 blue | 4,3 black | 2,1 white
static const _ringColors = <Color>[
Color(0xFFFFD23F), // 10
Color(0xFFFFD23F), // 9
Color(0xFFE5484D), // 8
Color(0xFFE5484D), // 7
Color(0xFF3B82C4), // 6
Color(0xFF3B82C4), // 5
Color(0xFF2B2B2B), // 4
Color(0xFF2B2B2B), // 3
Color(0xFFF5F5F5), // 2
Color(0xFFF5F5F5), // 1
];
@override
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
final radius = size.shortestSide / 2;
// Draw rings from outermost (1) inward to (10).
for (var i = _ringColors.length - 1; i >= 0; i--) {
final ringRadius = radius * (i + 1) / _ringColors.length;
final paint = Paint()..color = _ringColors[i];
canvas.drawCircle(center, ringRadius, paint);
}
// X ring (center dot).
canvas.drawCircle(
center,
radius * 0.05,
Paint()..color = const Color(0xFF8A6D00),
);
// Ring separator lines.
final stroke = Paint()
..color = const Color(0x55000000)
..style = PaintingStyle.stroke
..strokeWidth = ringStrokeWidth;
for (var i = 1; i <= _ringColors.length; i++) {
canvas.drawCircle(center, radius * i / _ringColors.length, stroke);
}
if (!showAllHits) return;
for (var i = 0; i < hitPoints.length; i++) {
final hp = hitPoints[i];
final point = Offset(
center.dx + hp.normalizedX * radius,
center.dy + hp.normalizedY * radius,
);
final isHighlight = i == highlightIndex;
final dotRadius = isHighlight ? radius * 0.045 : radius * 0.03;
canvas.drawCircle(
point,
dotRadius + 2,
Paint()..color = Colors.white,
);
canvas.drawCircle(
point,
dotRadius,
Paint()..color = isHighlight ? const Color(0xFF16A34A) : hitColor,
);
}
}
@override
bool shouldRepaint(covariant TargetFacePainter oldDelegate) {
return oldDelegate.hitPoints.length != hitPoints.length ||
oldDelegate.highlightIndex != highlightIndex ||
oldDelegate.hitColor != hitColor;
}
}