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

Flutter中如何为自定义环形分段图表添加独立边框

解决Flutter自定义环形分段图表的独立边框问题

你的问题出在直接用细描边的borderPaint绘制圆弧,无法形成包裹分段的完整边框。正确的思路是先绘制比填充更粗的黑色边框,再在边框上方绘制颜色填充,让填充覆盖边框中间区域,只保留外围的黑色边框。

修改后的完整代码如下:

class DonutChartPainter extends CustomPainter {
  final double planCalories;
  final double leftCalories;
  final double thickness = 40; 

  DonutChartPainter(this.planCalories, this.leftCalories);

  @override
  void paint(Canvas canvas, Size size) {
    final Paint fillPaint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = thickness
      ..strokeCap = StrokeCap.butt;

    final Paint borderPaint = Paint()
      ..color = Colors.black
      ..style = PaintingStyle.stroke
      // 边框宽度比填充大2,确保能露出1px的边框
      ..strokeWidth = thickness + 2;

    final double radius = size.width / 2;
    final Offset center = Offset(size.width / 2, size.height / 2);

    final double usedCalories = planCalories - leftCalories;
    final double leftAngle = (leftCalories / planCalories) * 2 * pi;
    final double usedAngle = (usedCalories / planCalories) * 2 * pi;

    final double separationOffset = 10;
    final Offset usedCenter = Offset(center.dx + separationOffset * cos(-pi / 2 + usedAngle / 2),
        center.dy + separationOffset * sin(-pi / 2 + usedAngle / 2));
    final Offset leftCenter = Offset(center.dx + separationOffset * cos(-pi / 2 + usedAngle + leftAngle / 2),
        center.dy + separationOffset * sin(-pi / 2 + usedAngle + leftAngle / 2));

    Rect usedOvalRect = Rect.fromCircle(center: usedCenter, radius: radius - thickness / 2);
    Rect leftOvalRect = Rect.fromCircle(center: leftCenter, radius: radius - thickness / 2);

    // 先绘制已消耗分段的黑色边框
    canvas.drawArc(usedOvalRect, -pi / 2, usedAngle, false, borderPaint);
    // 再绘制已消耗分段的颜色填充
    fillPaint.color = Colors.green;
    canvas.drawArc(usedOvalRect, -pi / 2, usedAngle, false, fillPaint);

    // 先绘制剩余分段的黑色边框
    canvas.drawArc(leftOvalRect, -pi / 2 + usedAngle, leftAngle, false, borderPaint);
    // 再绘制剩余分段的颜色填充
    fillPaint.color = Colors.lightGreen;
    canvas.drawArc(leftOvalRect, -pi / 2 + usedAngle, leftAngle, false, fillPaint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

关键修改说明:

  • 调整borderPaint的strokeWidth为thickness + 2:让边框比填充粗2个单位,这样填充覆盖中间后,上下左右各露出1px的黑色边框
  • 调整绘制顺序:先画边框,再画填充,确保填充在边框上方,只露出外围的边框
  • 保持分段的偏移和矩形参数一致:确保边框和填充完全对齐,不会出现错位

内容的提问来源于stack exchange,提问作者Kushnirenko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 10:33:17