You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 13:26:02