我想在 Flutter 中向我的应用程序添加一个饼图,它只是一个半圆/半甜甜圈或任何你所说的东西。 它应该看起来像这样:
但目前看起来像这样,我不知道是否有办法解决它:
主要:
body: Center(
//mainAxisAlignment: MainAxisAlignment.center,
child: Column(
children: [
Stack(
children: [
const Align(
alignment: Alignment.topCenter,
child: Padding(
padding: EdgeInsets.only(top: 5.0),
child: Text(
"Status",
style: TextStyle(
color: Colors.white,
fontSize: 25,
),
),
),
),
Align(
alignment: Alignment.topRight,
child: Padding(
padding: const EdgeInsets.only(right: 8, top: 5),
child: CircleAvatar(
radius: 17,
backgroundColor: Colors.lightBlue,
child: IconButton(
tooltip:
"Show tooltip",
onPressed: () {},
icon: const Icon(
Icons.question_mark,
color: Colors.white,
size: 18,
)),
),
),
),
],
),
Container(
width: 300.0,
height: 300.0,
//color: const Color.fromRGBO(72, 75, 80, 1),
color: const Color.fromRGBO(72, 75, 80, 1),
child: Stack(
alignment: Alignment.center,
children: [
// icon, svg, image
(isSwitched)
? Padding(
//padding: EdgeInsets.only(
// right: 8.0, left: 8.0, bottom: 75),
padding: EdgeInsets.all(8),
child: Text(
"Moderate",
style: TextStyle(
color: Colors.white,
fontSize: 23,
),
),
)
: Padding(
//padding: EdgeInsets.only(
// right: 8.0, left: 8.0, bottom: 75),
padding: EdgeInsets.all(8),
child: Text(
"Excellent",
style: TextStyle(
color: Colors.white,
fontSize: 23,
),
),
),
(isSwitched) ? MyPieChartYellow() : MyPieChart(),
],
)),
饼图:
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
class MyPieChart extends StatelessWidget {
const MyPieChart({super.key});
@override
Widget build(BuildContext context) {
return PieChart(
swapAnimationDuration: const Duration(milliseconds: 750),
swapAnimationCurve: Curves.easeInQuint,
PieChartData(centerSpaceRadius: 85.0, sections: [
PieChartSectionData(
value: 0,
color: Colors.red,
showTitle: false,
radius: 42,
),
PieChartSectionData(
value: 0,
color: Colors.yellow,
showTitle: false,
radius: 42,
),
PieChartSectionData(
value: 10,
color: Colors.green,
showTitle: false,
radius: 42,
)
]));
}
}
有人知道如何创建半图吗?我还没找到任何东西。
在这种情况下,fl_chart 不是适合该工作的工具。您可以使用自定义画家来绘制您自己的图表。
这是一个可能的实现:
class GaugeChart extends StatelessWidget {
const GaugeChart({
super.key,
required this.percent,
required this.color,
required this.backgroundColor,
this.strokeWidth = 10,
this.unitText,
required this.centerTextStyle,
});
/// percent is between 0 and 100
final double percent;
/// percentile arc color
final Color color;
/// background arc color
final Color backgroundColor;
/// arc stroke width
final double strokeWidth;
/// text shown after the text in center
final String? unitText;
/// text style of the text in center
final TextStyle centerTextStyle;
@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 2,
child: CustomPaint(
painter: GaugePainter(
percent: percent,
color: color,
backgroundColor: backgroundColor,
strokeWidth: strokeWidth,
unitText: unitText,
centerTextStyle: centerTextStyle,
),
),
);
}
}
class GaugePainter extends CustomPainter {
GaugePainter({
required this.percent,
required this.color,
required this.backgroundColor,
this.strokeWidth = 10.0,
this.unitText,
required this.centerTextStyle,
});
/// percent is between 0 and 100
final double percent;
/// percentile arc color
final Color color;
/// background arc color
final Color backgroundColor;
/// arc stroke width
final double strokeWidth;
/// text shown after the text in center
final String? unitText;
/// text style of the text in center
final TextStyle centerTextStyle;
@override
void paint(Canvas canvas, Size size) {
// calculate center and radius of circle
final center = Offset(size.width / 2, size.height);
final radius = size.width / 2 - strokeWidth / 2;
final fullArcPainter = Paint()
..color = backgroundColor
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round;
// when painter stroke cap is StrokeCap.round, it will add half of the
// stroke width to the start and end of arc. Therefore the angle is bigger
// then 2 * pi (=180) degree.
// This formula calculates the angle of the arc so the arc will be 180
// degree including the stroke width.
final angleWithRoundStroke = pi - strokeWidth / radius;
// This formula calculates the offset angle of the arc so the arc will be
// 180 degree including the stroke width.
final offsetAngle = pi + (strokeWidth / (2 * radius));
// Draw background arc
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
offsetAngle,
angleWithRoundStroke,
false,
fullArcPainter,
);
final percentPainter = Paint()
..color = color
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round;
double percentAngle;
if (percent >= 100) {
// catch case when percent is bigger than 100
percentAngle = angleWithRoundStroke;
} else {
// calculate angle of percent arc
percentAngle = percent * angleWithRoundStroke / 100;
}
// Draw percent arc
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
offsetAngle,
percentAngle,
false,
percentPainter,
);
// paint text
TextSpan textSpan = TextSpan(
text: percent.round().toString() + (unitText ?? ''),
style: centerTextStyle,
);
final textPainter = TextPainter(
text: textSpan,
textDirection: TextDirection.ltr,
);
textPainter.layout(
minWidth: 0,
maxWidth: size.width,
);
final xTextPosition = (size.width - textPainter.width) / 2;
final yTextPosition = (size.height - textPainter.height) * 3 / 4;
final textOffset = Offset(xTextPosition, yTextPosition);
textPainter.paint(canvas, textOffset);
}
@override
bool shouldRepaint(covariant GaugePainter oldDelegate) {
return oldDelegate.percent != percent;
}
}
请注意,您还可以使用动画控制器来动画更改。周围应该有导游。