115 lines
3.0 KiB
Dart
115 lines
3.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/svg.dart';
|
|
import 'package:vbvs_app/common/util/FitTool.dart';
|
|
|
|
class SegmentData {
|
|
final Color color;
|
|
final double value;
|
|
|
|
SegmentData({required this.color, required this.value});
|
|
}
|
|
|
|
class SegmentedCirclePainter extends CustomPainter {
|
|
final List<SegmentData> segments;
|
|
final double strokeWidth;
|
|
final double gapAngle; // 每段之间的间隔角度(单位:度)
|
|
|
|
SegmentedCirclePainter({
|
|
required this.segments,
|
|
this.strokeWidth = 6.0,
|
|
this.gapAngle = 4.0,
|
|
});
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
final double radius = size.width / 2;
|
|
final Offset center = Offset(size.width / 2, size.height / 2);
|
|
|
|
final Paint paint = Paint()
|
|
..style = PaintingStyle.stroke
|
|
..strokeWidth = strokeWidth
|
|
..strokeCap = StrokeCap.square;
|
|
|
|
final double totalValue = segments.fold(0, (sum, item) => sum + item.value);
|
|
final double totalGap = gapAngle * segments.length;
|
|
final double totalDrawAngle = 360.0 - totalGap;
|
|
|
|
double startAngle = -90.0; // 从顶部开始
|
|
|
|
for (var segment in segments) {
|
|
final double sweepAngle = (segment.value / totalValue) * totalDrawAngle;
|
|
|
|
paint.color = segment.color;
|
|
canvas.drawArc(
|
|
Rect.fromCircle(center: center, radius: radius - strokeWidth / 2),
|
|
radians(startAngle),
|
|
radians(sweepAngle),
|
|
false,
|
|
paint,
|
|
);
|
|
startAngle += sweepAngle + gapAngle;
|
|
}
|
|
}
|
|
|
|
double radians(double degrees) => degrees * 3.1415926 / 180;
|
|
|
|
@override
|
|
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
|
|
}
|
|
|
|
class SegmentedCircleWithCenterWidget extends StatelessWidget {
|
|
final List<SegmentData> segments;
|
|
final double strokeWidth;
|
|
final double gapAngle;
|
|
final Widget centerWidget;
|
|
final int trend;
|
|
|
|
const SegmentedCircleWithCenterWidget({
|
|
Key? key,
|
|
required this.segments,
|
|
this.strokeWidth = 6.0,
|
|
this.gapAngle = 4.0,
|
|
required this.centerWidget,
|
|
required this.trend,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Stack(
|
|
alignment: Alignment.center,
|
|
children: [
|
|
CustomPaint(
|
|
size: Size(200, 200), // 设置圆的尺寸
|
|
painter: SegmentedCirclePainter(
|
|
segments: segments,
|
|
strokeWidth: strokeWidth,
|
|
gapAngle: gapAngle,
|
|
),
|
|
),
|
|
centerWidget, // 放置自定义的中心 Widget
|
|
Positioned(
|
|
bottom: 140.rpx,
|
|
right: 50.rpx, // 放置在右侧
|
|
child: SvgPicture.asset(
|
|
_getTrendIcon(trend),
|
|
width: trend != 0 ? 14.rpx : 18.rpx,
|
|
height: trend != 0 ? 22.rpx : 6.rpx,
|
|
// color: themeController.currentColor.sc9,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
String _getTrendIcon(int? trend) {
|
|
switch (trend) {
|
|
case 0:
|
|
return 'assets/img/icon/score_equal.svg';
|
|
case 1:
|
|
return 'assets/img/icon/score_up.svg';
|
|
default:
|
|
return 'assets/img/icon/score_down.svg';
|
|
}
|
|
}
|
|
}
|