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

Flutter地图中绘制自定义重复图案折线及方向适配问题

在Flutter中实现沿折线重复的自定义图案折线(适配曲线)

核心思路

放弃直接用ImageShader整体填充路径,改为沿折线的切线方向逐段绘制图案,通过计算每段的切线角度、偏移量保证图案贴合折线走向,同时适配线宽。

具体实现步骤

  1. 拆分折线为微小线段
    用PathMetrics提取路径的度量信息,将原始折线拆分成一系列短直线段,线段越短,曲线处的图案贴合度越高:

    final pathMetrics = path.computeMetrics();
    for (final metric in pathMetrics) {
      const step = 5.0; // 控制分段精度,值越小曲线越平滑
      for (var distance = 0.0; distance < metric.length; distance += step) {
        final tangent = metric.getTangentForOffset(distance)!;
        final position = tangent.position;
        final angle = tangent.angle;
        // 处理当前分段的图案绘制
      }
    }
    
  2. 逐段绘制并适配参数
    针对每个分段完成以下操作:

    • 旋转图案:通过canvas.save()和canvas.rotate()让图案方向与折线切线一致
    • 适配线宽:将图案高度缩折线的线宽值,宽度保持自定义重复尺寸
    • 对齐位置:将图案中心对齐到折线当前位置,避免偏移
      示例代码片段:
    final lineWidth = 10.0; // 目标折线宽度
    final patternSize = Size(15.0, lineWidth); // 图案尺寸,高度匹配线宽
    
    canvas.save();
    canvas.translate(position.dx, position.dy);
    canvas.rotate(angle);
    // 替换为你的自定义图案(示例用矩形,实际可改为Image绘制)
    canvas.drawRect(
      Rect.fromCenter(center: Offset(0, 0), width: patternSize.width, height: patternSize.height),
      Paint()..color = Colors.blue,
    );
    canvas.restore();
    
  3. 实现无缝重复

    • 将分段的step值设置为图案的宽度,保证相邻图案无缝拼接
    • 如果用图片作为图案,提前将图片缩放到适配线宽的高度,避免绘制时重复缩放损耗性能
  4. 结合flutter_map使用
    在flutter_map的Polyline中自定义builder,返回包含CustomPaint的Widget:

    Polyline(
      points: yourPointsList,
      builder: (context, points, canvas, size) {
        final path = Path()
          ..addPolygon(points.map((p) => p.toOffset()).toList(), false);
        return CustomPaint(painter: PatternPolylinePainter(path, lineWidth, yourPatternImage));
      },
    )
    

关键注意事项

  • 性能平衡:step值过小会增加绘制开销,过大则曲线处图案会有棱角,可根据地图缩放级别动态调整
  • 坐标转换:在flutter_map中需将地图坐标正确转换为画布坐标,确保图案绘制位置准确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:47:07