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

Dart中环形图描边画笔模式下圆角绘制异常问题求助

解决描边模式下环形图圆角绘制问题

我明白你遇到的困扰了——用当前的路径方法做带圆角的环形图,填充模式能正常显示,但切换到描边模式就失效了。这是因为你现在的路径逻辑是为填充闭合区域设计的,而描边模式需要的是连续流畅的线条路径,两者的构建思路完全不一样。

问题根源

你当前通过addArc直接添加圆角弧、外弧和内弧,本质是在拼接出一个闭合的填充区域。但描边时,画笔是沿着路径的边缘绘制,这种方式会导致圆角弧和主弧的衔接处出现断裂,甚至圆角部分会画出完整的半圆轮廓,完全不符合我们要的“圆角连接内外半径”的效果。

解决方案:重构路径逻辑

我们需要重新搭建路径结构,让每一段线条(圆角、外弧、内弧)都能连续衔接,确保描边时线条能流畅过渡。下面是修改后的代码:

Path _getRoundedCornerArcPath(
  num innerRadius,
  num outerRadius,
  Offset? center,
  num startAngle,
  num endAngle,
  num? degree,
  CornerStyle cornerStyle,
  ChartPoint<dynamic> point,
) {
  final Path path = Path();
  final double strokeWidth = (outerRadius - innerRadius).abs() / 2;
  final Offset centerOffset = center!;

  // 角度转弧度的工具函数
  double degToRad(num deg) => deg * pi / 180;

  // 根据角度和半径计算对应点的坐标
  Offset getPoint(num angle, num radius) {
    final double rad = degToRad(angle);
    return Offset(
      centerOffset.dx + radius * cos(rad),
      centerOffset.dy + radius * sin(rad),
    );
  }

  // 计算外弧、内弧的起点和终点
  final Offset outerStart = getPoint(startAngle, outerRadius);
  final Offset outerEnd = getPoint(endAngle, outerRadius);
  final Offset innerStart = getPoint(startAngle, innerRadius);
  final Offset innerEnd = getPoint(endAngle, innerRadius);

  // 处理起始圆角
  if (cornerStyle == CornerStyle.startCurve || cornerStyle == CornerStyle.bothCurve) {
    final Offset startCornerCenter = getPoint(startAngle, (innerRadius + outerRadius) / 2);
    // 从内起点开始,画半圆连接到外起点
    path.moveTo(innerStart.dx, innerStart.dy);
    path.addArc(
      Rect.fromCircle(center: startCornerCenter, radius: strokeWidth),
      degToRad(startAngle + 90),
      degToRad(180),
    );
  } else {
    // 无圆角时直接直线连接内外起点
    path.moveTo(innerStart.dx, innerStart.dy);
    path.lineTo(outerStart.dx, outerStart.dy);
  }

  // 绘制外弧:从外起点到外终点
  path.addArc(
    Rect.fromCircle(center: centerOffset, radius: outerRadius.toDouble()),
    degToRad(startAngle),
    degToRad(endAngle - startAngle),
  );

  // 处理结束圆角
  if (cornerStyle == CornerStyle.endCurve || cornerStyle == CornerStyle.bothCurve) {
    final Offset endCornerCenter = getPoint(endAngle, (innerRadius + outerRadius) / 2);
    // 从外终点画半圆连接到内终点
    path.addArc(
      Rect.fromCircle(center: endCornerCenter, radius: strokeWidth),
      degToRad(endAngle - 90),
      degToRad(180),
    );
  } else {
    // 无圆角时直接直线连接外终点到内终点
    path.lineTo(innerEnd.dx, innerEnd.dy);
  }

  // 绘制内弧:从内终点回到内起点,闭合路径
  path.addArc(
    Rect.fromCircle(center: centerOffset, radius: innerRadius.toDouble()),
    degToRad(endAngle),
    degToRad(startAngle - endAngle),
  );

  return path;
}

关键改进点

  1. 路径连续性:用moveTo和lineTo确保每一段路径的起点和前一段的终点精准衔接,彻底避免描边时的断裂问题。
  2. 圆角角度校准:调整了圆角半圆的起始角度,让它刚好贴合外弧和内弧的端点,不会画出多余的轮廓。
  3. 代码复用优化:提取了角度转弧度和点坐标计算的工具函数,让逻辑更清晰,减少重复计算。

这样修改后,不管是填充模式还是描边模式,带圆角的环形图都能正确渲染了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 06:02:27