85 lines
2.2 KiB
Dart
85 lines
2.2 KiB
Dart
import 'dart:math';
|
|
import 'package:flutter/material.dart';
|
|
|
|
class TargetProgressChart extends StatelessWidget {
|
|
final double percent;
|
|
final double size;
|
|
|
|
const TargetProgressChart({
|
|
super.key,
|
|
required this.percent,
|
|
this.size = 110,
|
|
});
|
|
|
|
// Format persentase: tampilkan desimal hanya jika tidak bulat
|
|
// Contoh: 100.0 → "100%", 5.01 → "5.01%", 50.5 → "50.5%"
|
|
String get _percentLabel {
|
|
if (percent == percent.roundToDouble()) {
|
|
return '${percent.toInt()}%';
|
|
}
|
|
// Hilangkan trailing zero: 5.10 → "5.1", 5.01 → "5.01"
|
|
final formatted = percent.toStringAsFixed(2);
|
|
final trimmed = formatted.replaceAll(RegExp(r'0+$'), '');
|
|
return '$trimmed%';
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SizedBox(
|
|
width: size,
|
|
height: size,
|
|
child: CustomPaint(
|
|
painter: _PieChartPainter(percent: percent),
|
|
child: Center(
|
|
child: Text(
|
|
_percentLabel,
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
// Sedikit lebih kecil agar teks desimal muat
|
|
fontSize: size * 0.15,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _PieChartPainter extends CustomPainter {
|
|
final double percent;
|
|
_PieChartPainter({required this.percent});
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
final center = Offset(size.width / 2, size.height / 2);
|
|
final radius = size.width / 2;
|
|
|
|
final bgPaint = Paint()
|
|
..color = Colors.white.withOpacity(0.2)
|
|
..style = PaintingStyle.fill;
|
|
canvas.drawCircle(center, radius, bgPaint);
|
|
|
|
final progressPaint = Paint()
|
|
..color = Colors.white.withOpacity(0.5)
|
|
..style = PaintingStyle.fill;
|
|
|
|
final sweepAngle = 2 * pi * (percent / 100);
|
|
canvas.drawArc(
|
|
Rect.fromCircle(center: center, radius: radius),
|
|
-pi / 2,
|
|
sweepAngle,
|
|
true,
|
|
progressPaint,
|
|
);
|
|
|
|
final innerPaint = Paint()
|
|
..color = const Color(0xFF5B9BD5)
|
|
..style = PaintingStyle.fill;
|
|
canvas.drawCircle(center, radius * 0.55, innerPaint);
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(covariant _PieChartPainter old) => old.percent != percent;
|
|
}
|