多边形 Polygon

多边形(Polygon)用于在地图上绘制封闭区域,支持填充色、描边、虚线、纹理描边和带洞多边形。

本文档介绍 Polygon 的创建、样式配置以及带洞多边形的注意事项。



创建 Polygon

Polygon(
  id: 'pg1',
  points: const [
    LatLng(39.90, 116.39),
    LatLng(39.90, 116.42),
    LatLng(39.93, 116.42),
    LatLng(39.93, 116.39),
  ],
  fillColor: const Color(0x7F00FF00),
  strokeColor: const Color(0xFF000000),
  strokeWidth: 5,
)

添加到地图:

TencentMap(
  polygons: {polygon},
  ...
)

Polygon 参数

参数 类型 默认值 说明
id String? 自动生成 唯一标识
points List<LatLng> 必填 外轮廓顶点(≥3 个)
holePoints List<List<LatLng>> [] 洞的坐标列表
fillColor Color Color(0x7F00FF00) 填充色
strokeColor Color Color(0xFF000000) 描边色
strokeWidth double 10 描边宽度(逻辑像素)
dashPattern List<int> [] 虚线模式
strokeTexture BitmapDescriptor? null 纹理描边
strokeTextureSpacing int 0 纹理间距
displayLevel int 2 显示层级
visible bool true 是否可见
zIndex int 0 层级
onTap PolygonTapCallback? null 点击回调(参数为 polygonId

填充与描边

Polygon(
  id: 'pg1',
  points: points,
  fillColor: const Color(0x7F0000FF),  // 半透明蓝色填充
  strokeColor: const Color(0xFF000000), // 黑色描边
  strokeWidth: 5,
)

虚线描边

Polygon(
  id: 'dashed',
  points: points,
  fillColor: Colors.transparent,
  strokeColor: Colors.red,
  dashPattern: [20, 10], // 20px 实线 + 10px 空白
)

纹理描边

Polygon(
  id: 'texture',
  points: points,
  strokeTexture: BitmapDescriptor.fromAsset('assets/border_texture.png'),
  strokeTextureSpacing: 0,
  strokeWidth: 20,
)

注意strokeTexturedashPattern 互斥,设置纹理后虚线不生效。


带洞多边形

带洞多边形允许在一个外轮廓内挖出一个或多个洞:

Polygon(
  id: 'withHole',
  points: outerPoints, // 外轮廓
  holePoints: [
    // 第一个洞
    [
      LatLng(39.91, 116.40),
      LatLng(39.91, 116.41),
      LatLng(39.92, 116.41),
      LatLng(39.92, 116.40),
    ],
  ],
  fillColor: const Color(0x7F00FF00),
  strokeColor: Colors.black,
)

声明式更新

基本原理

Polygon 通过 Set<Polygon> 以声明式方式管理。插件在 Widget 重建时自动 diff 新旧两个 Set,计算出增/删/改三类变更并推送到原生层:

  • diff 按 id 索引:内部用 Map<String, Polygon> 索引,不依赖 Set 的 hashCode
  • 属性比较用 ==:Polygon 重写了 ==,比较 points/holePoints/fillColor/strokeWidth/dashPattern 等全部业务属性(⚠️ 也比较 onTap 回调)
  • 对象不可变:Polygon 是 @immutable,修改属性必须用 copyWith 创建新对象

推荐用法:Map 管理 + Set 传入

final Map<String, Polygon> _polygons = {};

// 添加
_polygons['pg1'] = Polygon(
  id: 'pg1',
  points: const [
    LatLng(39.90, 116.39),
    LatLng(39.90, 116.42),
    LatLng(39.93, 116.42),
    LatLng(39.93, 116.39),
  ],
  fillColor: const Color(0x7F00FF00),
);

// 更新(必须 copyWith,不能原地改字段)
_polygons['pg1'] = _polygons['pg1']!.copyWith(fillColor: Colors.red);

// 更新点位(points 是 List,必须创建新 List)
_polygons['pg1'] = _polygons['pg1']!.copyWith(
  points: [..._polygons['pg1']!.points, const LatLng(39.94, 116.40)],
);

// 删除
_polygons.remove('pg1');

// 传入 Widget
TencentMap(polygons: Set<Polygon>.of(_polygons.values));

哪些情况会导致更新不触发

错误写法 原因 正确写法
原地修改 points / holePoints 列表:polygon.points.add(newPoint) Polygon 对象引用不变 → == 短路 identical → 判定无变化 → 不触发。即使列表内容变了,== 里的 _listEquals / _holeListEquals 也不会被执行 polygon.copyWith(points: [...polygon.points, newPoint])
在同一 Set 上 add copyWith 后的对象:_polygons.add(pg.copyWith(fillColor: Colors.red)) hashCode 仅基于 id(相同),但 == 为 false(属性不同)→ Set 同时保留新旧两个对象 → diff 按 id 索引只取最后一个,行为不可预测 创建全新 Set,或用 Map 管理
两个 Polygon 用同一个 id diff 按 id 索引成 Map 时后者覆盖前者 → 变更丢失 确保每个 Polygon 有唯一 id(不传 id 时自动生成)
修改了 State 变量但没调 setState Widget 不重建 → didUpdateWidget 不触发 → diff 不执行 必须在 setState 内修改变量

提示:Polygon 的 == 会比较 onTap 回调。如果在 build 方法中内联写 onTap: () {},每次重建都会产生新的闭包引用 → onTap != oldOnTap → 触发不必要的更新。建议将回调存储为成员变量。

本页内容