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

Dart中如何获取自定义Path的中点?

如何获取自定义Path的中点并在路径动画中显示标记

我的路径绘制代码

class PathPainter extends CustomPainter {
  PathPainter({required this.progress});

  final double progress;

  @override
  void paint(Canvas canvas, Size size) {
    var path = createPath(size);
    try {
      PathMetric pathMetric = path.computeMetrics().first;
      Path extractPath =
          pathMetric.extractPath(0.0, pathMetric.length * progress);

      // 绘制路径起点圆圈
      canvas.drawCircle(
          Offset(0, size.height), 8.0, Paint()..color = Colors.green);

      canvas.drawPath(extractPath, myPaint);

      var metric = extractPath.computeMetrics().first;
      final offset = metric.getTangentForOffset(metric.length)!.position;
      print(offset);

      // 尝试通过静态坐标判断中点的代码(已注释)
      // if (offset == const Offset(30.5, 275.8)) {
      //   print("i am matched");
      //   canvas.drawCircle(Offset(30.5, 275.8), 8.0, Paint()..color = Colors.green);
      // }

      canvas.drawCircle(offset, 8.0, Paint()..color = Colors.green);
    } catch (e) {}
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}

需求背景

我希望在路径逐步绘制的动画过程中,在路径的中点位置添加一个圆圈标记。

已尝试的方案(均未成功)

方案一:通过静态Offset判断位置

if (offset == const Offset(30.5, 275.8)) {
  print("i am matched");
  canvas.drawCircle(Offset(30.5, 275.8), 8.0, Paint()..color = Colors.green);
}

方案二:通过路径长度判断

var length = pathMetric.length / 2;

if (extractPath.computeMetrics().length == length) {
  canvas.drawCircle(offset, 8.0,  Paint()..color = Colors.green);
}

解决方案

你不需要通过静态坐标或者错误的长度判断来获取中点,直接利用PathMetric就能精准获取路径中点的坐标,并且可以根据动画进度控制是否显示这个标记:

修改后的paint方法代码如下:

@override
void paint(Canvas canvas, Size size) {
  var path = createPath(size);
  try {
    PathMetric pathMetric = path.computeMetrics().first;
    double totalLength = pathMetric.length;
    // 获取路径中点的长度位置
    double midPointLength = totalLength / 2;
    // 获取中点的坐标
    Tangent? midTangent = pathMetric.getTangentForOffset(midPointLength);
    Offset midPoint = midTangent?.position ?? Offset.zero;

    Path extractPath = pathMetric.extractPath(0.0, totalLength * progress);

    // 绘制起点圆圈
    canvas.drawCircle(Offset(0, size.height), 8.0, Paint()..color = Colors.green);

    // 绘制当前进度的路径
    canvas.drawPath(extractPath, myPaint);

    // 获取当前绘制路径的终点坐标
    var metric = extractPath.computeMetrics().first;
    final offset = metric.getTangentForOffset(metric.length)!.position;
    canvas.drawCircle(offset, 8.0, Paint()..color = Colors.green);

    // 当动画进度达到或超过50%时,绘制中点标记
    if (progress >= 0.5) {
      canvas.drawCircle(midPoint, 8.0, Paint()..color = Colors.red);
    }
    // 如果需要不管进度都显示中点(即使路径还没画到),可以去掉上面的if判断
    // canvas.drawCircle(midPoint, 8.0, Paint()..color = Colors.red);

  } catch (e) {
    print(e);
  }
}

关键说明

  • 精准获取中点:利用pathMetric.getTangentForOffset(totalLength / 2)直接拿到路径中点的Tangent对象,从中提取坐标,这是最可靠的方式,不需要依赖静态坐标。
  • 进度控制显示:通过progress >= 0.5判断动画是否推进到中点位置,此时再绘制中点标记,符合你“动画推进过程中添加圆圈”的需求。
  • 避免错误判断:之前的方案二错误地使用了extractPath.computeMetrics().length(这是路径度量的数量,不是路径长度),正确的做法是直接使用原路径的总长度计算中点。

内容的提问来源于stack exchange,提问作者Abd ur Rehman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 21:45:35