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
相关产品推荐
相关产品推荐

