使用 CustomPaint 小部件可以轻松实现与图表非常相似的版本。
要实现这一点,您只需要一个非常基本的 CustomPainter 来在画布上绘制弧线。
舍入效果是通过用于绘制笔划的 Paint 的 linesCap 属性来实现的。遗憾的是 StrokeCap 仅支持
圆形和方形笔画结尾。
这样是无法实现像你截图那样的圆角矩形效果的。
颜色是通过为每个笔划使用单独的 Paint 来实现的。
// this is used to pass data about chart values to the widget
class PieChartData {
const PieChartData(this.color, this.percent);
final Color color;
final double percent;
}
// our pie chart widget
class PieChart extends StatelessWidget {
PieChart({
required this.data,
required this.radius,
this.strokeWidth = 8,
this.child,
Key? key,
}) : // make sure sum of data is never ovr 100 percent
assert(data.fold<double>(0, (sum, data) => sum + data.percent) <= 100),
super(key: key);
final List<PieChartData> data;
// radius of chart
final double radius;
// width of stroke
final double strokeWidth;
// optional child; can be used for text for example
final Widget? child;
@override
Widget build(context) {
return CustomPaint(
painter: _Painter(strokeWidth, data),
size: Size.square(radius),
child: SizedBox.square(
// calc diameter
dimension: radius * 2,
child: Center(
child: child,
),
),
);
}
}
// responsible for painting our chart
class _PainterData {
const _PainterData(this.paint, this.radians);
final Paint paint;
final double radians;
}
class _Painter extends CustomPainter {
_Painter(double strokeWidth, List<PieChartData> data) {
// convert chart data to painter data
dataList = data
.map((e) => _PainterData(
Paint()
..color = e.color
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth
..strokeCap = StrokeCap.round,
// remove padding from stroke
(e.percent - _padding) * _percentInRadians,
))
.toList();
}
static const _percentInRadians = 0.062831853071796;
// this is the gap between strokes in percent
static const _padding = 4;
static const _paddingInRadians = _percentInRadians * _padding;
// 0 radians is to the right, but since we want to start from the top
// we'll use -90 degrees in radians
static const _startAngle = -1.570796 + _paddingInRadians / 2;
late final List<_PainterData> dataList;
@override
void paint(Canvas canvas, Size size) {
final rect = Offset.zero & size;
// keep track of start angle for next stroke
double startAngle = _startAngle;
for (final data in dataList) {
final path = Path()..addArc(rect, startAngle, data.radians);
startAngle += data.radians + _paddingInRadians;
canvas.drawPath(path, data.paint);
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return oldDelegate != this;
}
}
您可以查看 dartpad 来尝试一个工作示例。
我确信您在该图片中提供的相同图表可以 使用 CustomPainter 实现,但这会复杂得多。
您好,请根据您的要求尝试这个。 Flutter 圆形图表中的甜甜圈图(SfCircularChart)。 “https://help.syncfusion.com/flutter/circular-charts/chart-types/doughnut-chart”