如何在Flutter中构建指定样式的自定义饼图?
在Flutter中实现指定样式饼图的方案
一、自定义绘制(最灵活的实现方式)
如果现有第三方库无法满足样式需求,用CustomPaint自定义绘制是最可靠的方案,能完全复刻你需要的饼图细节(比如中心镂空、扇区间隙、特殊标注等)。核心是通过Canvas的路径绘制能力,逐个处理每个扇区的形状、颜色和间隙。
以下是一个基础的实现示例:
class CustomGapPieChart extends StatelessWidget { final List<double> data; final List<Color> sectionColors; final double sectionGapAngle; // 扇区间隙角度(单位:度) final double innerHollowRatio; // 中心镂空半径占外半径的比例(0-1) const CustomGapPieChart({ super.key, required this.data, required this.sectionColors, this.sectionGapAngle = 2.0, this.innerHollowRatio = 0.4, }); @override Widget build(BuildContext context) { return CustomPaint( size: const Size(300, 300), painter: _GapPieChartPainter( data: data, colors: sectionColors, gapAngle: sectionGapAngle, innerRatio: innerHollowRatio, ), ); } } class _GapPieChartPainter extends CustomPainter { final List<double> data; final List<Color> colors; final double gapAngle; final double innerRatio; _GapPieChartPainter({ required this.data, required this.colors, required this.gapAngle, required this.innerRatio, }); @override void paint(Canvas canvas, Size size) { final center = Offset(size.width / 2, size.height / 2); final outerRadius = size.width / 2; final totalValue = data.reduce((a, b) => a + b); double startAngle = -90 * (pi / 180); // 从顶部开始绘制 for (int i = 0; i < data.length; i++) { // 计算当前扇区的角度(扣除间隙) final sweepAngle = (data[i] / totalValue) * 2 * pi - (gapAngle * pi / 180); final paint = Paint()..color = colors[i]; // 用Path绘制带镂空的扇区 final path = Path() ..moveTo(center.dx, center.dy) ..arcTo( Rect.fromCircle(center: center, radius: outerRadius), startAngle, sweepAngle, false, ) ..arcTo( Rect.fromCircle(center: center, radius: outerRadius * innerRatio), startAngle + sweepAngle, -sweepAngle, false, ) ..close(); canvas.drawPath(path, paint); // 更新下一个扇区的起始角度 startAngle += sweepAngle + (gapAngle * pi / 180); } } @override bool shouldRepaint(covariant _GapPieChartPainter oldDelegate) { return data != oldDelegate.data || colors != oldDelegate.colors || gapAngle != oldDelegate.gapAngle || innerRatio != oldDelegate.innerRatio; } }
使用时只需传入数据、颜色列表,还能根据需求扩展添加扇区标签、阴影、渐变等细节。
二、修改现有图表库的源码
如果你之前尝试过fl_chart、charts_flutter这类主流库,可以通过修改源码或自定义渲染逻辑适配样式:
- 比如
fl_chart的PieChart,可通过PieChartSectionData的borderSide、radius属性调整间隙和大小,还能自定义PieChartSection的widget实现特殊标注; - 若库默认不支持扇区间隙,找到绘制扇区的核心代码,在每个扇区绘制时预留固定角度的间隙即可。
三、选用定制化强的小众库
可以在pub.dev搜索“donut chart”“gap pie chart”,部分小众库原生支持中心镂空、扇区间隙这类特殊样式,能省去自定义绘制的时间成本。
内容的提问来源于stack exchange,提问作者Hasnain Bhatti
相关产品推荐
相关产品推荐

