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

Flutter中如何在Google Maps多边形内部或周边添加文字标注

Flutter Google Maps 多边形添加文字标识实现方案

官方提供的Polygon类确实没有内置label属性,目前生产环境通用的实现逻辑是计算多边形的锚点位置(内部中心点/外围指定位置),将自定义文字以无默认图标的透明Marker形式叠加在对应坐标,和现有Marker加文字的逻辑完全兼容,不需要改动已写好的多边形绘制代码。


步骤1:计算文字放置的锚点坐标

如果要把文字放在多边形内部,常规场景直接计算多边形顶点的几何质心即可;如果要放在外围,基于质心做对应方向的经纬度偏移就行。

// 传入多边形顶点列表,返回多边形几何中心点坐标
LatLng calculatePolygonCentroid(List<LatLng> points) {
  double totalLat = 0;
  double totalLng = 0;
  for (LatLng point in points) {
    totalLat += point.latitude;
    totalLng += point.longitude;
  }
  return LatLng(totalLat / points.length, totalLng / points.length);
}

带孔洞的复杂凹多边形用平均坐标可能落在孔洞区域,替换成专业多边形质心计算算法、或手动微调坐标即可。

步骤2:生成仅显示文字的Marker图标

不需要显示默认的Marker图钉,直接通过Canvas绘制文字生成位图,转成Google Map可识别的BitmapDescriptor。

import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

Future<BitmapDescriptor> buildTextMarkerIcon(
  String labelText, {
  double fontSize = 14,
  Color textColor = Colors.black87,
  Color bgColor = Colors.white70,
}) async {
  final recorder = ui.PictureRecorder();
  final canvas = Canvas(recorder);
  final textPainter = TextPainter(
    textDirection: TextDirection.ltr,
    text: TextSpan(
      text: labelText,
      style: TextStyle(
        fontSize: fontSize,
        color: textColor,
        fontWeight: FontWeight.w500,
        backgroundColor: bgColor,
      ),
    ),
  )..layout();

  // 将文字绘制在画布中心,避免偏移
  textPainter.paint(canvas, Offset(-textPainter.width/2, -textPainter.height/2));

  final img = await recorder.endRecording().toImage(
    textPainter.width.toInt(),
    textPainter.height.toInt()
  );
  final byteData = await img.toByteData(format: ui.ImageByteFormat.png);
  return BitmapDescriptor.fromBytes(byteData!.buffer.asUint8List());
}

步骤3:绑定文字Marker与多边形

遍历所有多边形生成对应文字Marker,加入地图的Marker集合即可。

// 示例多边形列表
List<Polygon> polygonList = [
  Polygon(
    polygonId: const PolygonId('poly-101'),
    points: [/* 对应多边形顶点坐标 */],
    fillColor: Colors.blue.withOpacity(0.3),
    strokeColor: Colors.blue,
    strokeWidth: 2,
  ),
  Polygon(
    polygonId: const PolygonId('poly-102'),
    points: [/* 对应多边形顶点坐标 */],
    fillColor: Colors.green.withOpacity(0.3),
    strokeColor: Colors.green,
    strokeWidth: 2,
  )
];

Future<Set<Marker>> generatePolygonLabelMarkers() async {
  final labelMarkers = <Marker>{};
  for (final polygon in polygonList) {
    final label = polygon.polygonId.value;
    // 替换成偏移后的坐标即可把文字放到外围
    final position = calculatePolygonCentroid(polygon.points);
    final icon = await buildTextMarkerIcon(label);

    labelMarkers.add(
      Marker(
        markerId: MarkerId('label_${polygon.polygonId.value}'),
        position: position,
        icon: icon,
        anchor: const Offset(0.5, 0.5), // 让文字中心对齐锚点坐标
        consumeTapEvents: false, // 不拦截点击事件,避免影响多边形交互
      )
    );
  }
  return labelMarkers;
}

适配注意事项

  • 该方案下文字大小不会随地图缩放变化,始终保持设定的屏幕显示尺寸,符合常规地图标签的交互习惯
  • 需要把标签放在多边形外围时,基于计算出的质心做经纬度偏移即可,比如在多边形上方显示标签,可给纬度值加0.0005~0.002的偏移,偏移量根据多边形实际大小调整
  • 不建议用Stack嵌套普通组件+坐标转换的方式实现,多边形数量较多时会出现明显性能卡顿,Marker方案由地图原生渲染,性能更稳定
  • 如果需要标签随多边形倾斜、旋转,可在生成Marker时开启对应平贴属性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 03:15:48