折线 Polyline

折线(Polyline)用于在地图上绘制一系列连接的线段,支持实线、虚线、纹理线(色切片/重复纹理/足迹线)、渐变色、分段着色等多种样式。

本文档介绍 Polyline 的创建、样式配置以及属性联动规则。



创建 Polyline

Polyline(
  id: 'p1',
  points: const [
    LatLng(39.90, 116.39),
    LatLng(39.92, 116.41),
    LatLng(39.94, 116.43),
  ],
  color: const Color(0xFF2196F3),
  width: 8,
)

添加到地图:

TencentMap(
  polylines: {polyline},
  ...
)

Polyline 参数

参数 类型 默认值 说明
id String? 自动生成 唯一标识
points List<LatLng> 必填 折线顶点,至少 2 个
width double 10.0 线宽(逻辑像素)
color Color Color(0xC600A3FF) 线颜色(ARGB)
visible bool true 是否可见
alpha double 1.0 线透明度 [0, 1]
zIndex int 0 堆叠顺序
arrow bool false 是否绘制箭头
lineType LineType solid 线型:solid/dashed/texture
lineCap bool true 是否圆头端点
textureLineType TextureLineType? null 纹理线子类型(仅 lineType.texture 时生效)
segmentStyles List<SegmentStyle>? null 分段样式(colorSlice 模式)
colorTexture BitmapDescriptor? null 纹理图片
arrowTexture BitmapDescriptor? null 自定义箭头图标
arrowSpacing int? null 箭头间距(逻辑像素)
pattern List<int>? null 虚线模式 [实线长度, 间隔长度, …]
borderWidth double 0 描边宽度(逻辑像素)
borderColor Color Color(0xFF000000) 描边颜色
segmentColors List<SegmentColor>? null 分段填充色
displayLevel int 0 显示层级(0=道路之上)
gradient bool? null 是否启用渐变色
onTap PolylineTapCallback? null 点击回调

线型枚举

LineType

说明
LineType.solid 实线 / 彩虹线(默认)
LineType.dashed 虚线(通过 pattern 控制间隔)
LineType.texture 纹理线(需配合 textureLineType 指定子类型)

TextureLineType

说明
TextureLineType.colorSlice 纹理色切片(配合 segmentStyles 指定各段颜色索引)
TextureLineType.repeat 重复纹理(配合 colorTexture 指定纹理图片)
TextureLineType.footprint 足迹线效果

线样式

实线 + 描边

Polyline(
  id: 'solid',
  points: points,
  color: const Color(0xFF2196F3),
  width: 8,
  borderWidth: 2,
  borderColor: const Color(0xFF0D47A1),
  lineCap: true, // 圆头
)

虚线 + 箭头

Polyline(
  id: 'dashed',
  points: points,
  color: const Color(0xFFE53935),
  width: 10,
  lineType: LineType.dashed,
  pattern: const [30, 20], // 30px 实线 + 20px 空白
  arrow: true,
)

纹理线 - 重复纹理

Polyline(
  id: 'texture',
  points: points,
  width: 16,
  lineType: LineType.texture,
  textureLineType: TextureLineType.repeat,
  colorTexture: BitmapDescriptor.fromAsset('assets/nav_arrow.png'),
)

效果图如下:

Polyline:实线/虚线/纹理线

Polyline demo:实线、虚线、纹理线效果对比


渐变色

Polyline(
  id: 'gradient',
  points: points,
  width: 10,
  gradient: true,
  color: const Color(0xFF2196F3),
)

注意gradientbool? 类型,设为 true 启用渐变色。渐变沿折线方向从第一个点到最后一个点过渡。修改此字段会触发折线重建。


分段着色

Polyline(
  id: 'segment',
  points: points, // 4 个点 = 3 段
  width: 12,
  segmentColors: [
    SegmentColor(startIndex: 0, endIndex: 1, color: const Color(0xFF4CAF50)),  // 绿
    SegmentColor(startIndex: 1, endIndex: 2, color: const Color(0xFFFFC107)),  // 黄
    SegmentColor(startIndex: 2, endIndex: 3, color: const Color(0xFFE53935)),  // 红
  ],
)

注意segmentColorsList<SegmentColor>? 类型,每个 SegmentColor 包含 startIndexendIndexcolor 和可选的 borderColor。修改此字段会触发折线重建。


属性联动规则

lineTypetextureLineTypegradientsegmentColors 等属性之间存在联动关系——某些属性组合下,部分字段会被忽略或压制。以下是完整规则。

总体原则

  • lineType 决定大分支(solid / dashed / texture
  • textureLineTypelineType=texture 时决定纹理子类型(colorSlice / repeat / footprint
  • gradient 仅在 lineType=solid + segmentColors 正确设置时有视觉效果
  • 插件 Dart 层 toMap() 始终完整序列化所有字段(含当前不生效的字段),由原生适配层做"生效性过滤"

联动关系图

lineType ──────────────┬──→ 决定大分支 (solid / dashed / texture)
                       │
                       ├── dashed → 压制: arrow, arrowTexture, arrowSpacing,
                       │              colorTexture, segmentColors, segmentStyles, gradient
                       │              注入: pattern 默认值 [30,20](若用户未设)
                       │
                       ├── texture → 压制: pattern, borderWidth, borderColor, gradient
                       │    │
                       │    └── textureLineType
                       │         ├── colorSlice → 压制: color, segmentColors
                       │         │                 要求: segmentStyles(必须设置)
                       │         │                 允许: arrow
                       │         ├── repeat    → 压制: arrow, arrowTexture, arrowSpacing, color
                       │         └── footprint → 同 repeat(但 arrowSpacing 语义复用为足迹间距)
                       │
                       └── solid → 大多数字段正常生效
                            │
                            ├── segmentColors 有值 → 覆盖 color, borderColor(每段自带)
                            │
                            └── gradient=true + segmentColors 有效
                                 → 压制: borderWidth, borderColor
                                   要求: segmentColors

arrow ──→ 控制 arrowTexture / arrowSpacing 是否有意义
          arrow=false 时这两个字段不传给 SDK

lineType = solid(实线,默认)

字段 生效 备注
points / width / visible / alpha / zIndex / displayLevel / lineCap / onTap 始终生效
color 如果设了 segmentColors 则被覆盖
arrow / arrowTexture / arrowSpacing arrowTexture/arrowSpacingarrow=true
segmentColors 设了则替代 color/borderColor
borderWidth / borderColor ⚠️ gradient=true 时不生效;segmentColors 各段自带 borderColor 覆盖全局值
gradient ⚠️ 仅当 segmentColors 正确设置时生效;生效后 borderWidth/borderColor 被忽略
pattern 仅 dashed 模式
colorTexture 仅 texture 模式
textureLineType 仅 texture 模式
segmentStyles 仅 texture + colorSlice 模式

lineType = dashed(虚线)

字段 生效 备注
points / width / color / visible / alpha / zIndex / displayLevel / lineCap / onTap 始终生效
pattern 不设则自动注入默认值 [30, 20]
arrow 插件层强制传 false 给 SDK(统一双端行为)
arrowTexture / arrowSpacing
borderWidth / borderColor 当前实现中 dashed 不传 border
colorTexture / textureLineType
segmentColors / segmentStyles
gradient

lineType = texture + textureLineType = colorSlice(色卡纹理)

字段 生效 备注
points / width / visible / alpha / zIndex / displayLevel / onTap 始终生效
colorTexture 不设则用 SDK 默认纹理(10 行预设颜色)
segmentStyles 必须设置,指定每段用纹理的第几行颜色
arrow / arrowTexture / arrowSpacing colorSlice 支持箭头
color 颜色由 segmentStyles.colorImageIndex 决定
segmentColors / borderWidth / borderColor / pattern / gradient

lineType = texture + textureLineType = repeat(重复纹理)

字段 生效 备注
points / width / visible / alpha / zIndex / displayLevel / onTap 始终生效
colorTexture 必须设置,否则无纹理可重复
segmentStyles ⚠️ 可选(iOS 支持分段指定)
arrow / arrowTexture / arrowSpacing repeat 模式不支持箭头
color / segmentColors / borderWidth / borderColor / pattern / gradient

lineType = texture + textureLineType = footprint(足迹纹理)

与 repeat 基本一致,但有以下差异:

字段 生效 备注
colorTexture 必须设置
arrowSpacing ⚠️ 语义复用:控制足迹间距。Android 默认 150px,iOS 默认 60pt
segmentStyles ⚠️ 可选(iOS 内部自动注入默认 segmentStyle)
arrow / arrowTexture
color / segmentColors / borderWidth / borderColor / pattern / gradient

gradient 规则详解

  • gradient=true 仅在 lineType=solidsegmentColors 正确设置时有视觉效果
  • gradient 生效时 borderWidth/borderColor 的描边被 SDK 忽略
  • 渐变以 segmentColorsstartIndex 作为颜色过渡标记点
  • 如果 gradient=truesegmentColors 为空/null,则 gradient 实际不生效(无渐变标记点,SDK 退化为纯色线)
  • 如果用户同时设了 gradient=true + borderWidth>0,以 gradient 优先,描边静默丢弃

arrow 互斥处理规则

  • lineType=dashed 时,传给原生 SDK 的 arrow 强制为 false(不管用户在 Dart 层设了什么)
  • Dart 层 Polyline.arrow 保持用户原始值(用于 == / copyWith / toMap 序列化)
  • lineType=texturetextureLineType=repeat/footprint 时,arrow 同样不生效

⚠️ 已知平台差异:箭头与虚线互斥

当同时设置 arrow: true + lineType: LineType.dashed 时,双端 SDK 的优先级不同

平台 真实表现
Android 箭头优先显示,虚线被 SDK 忽略(线变成实线 + 箭头)
iOS 虚线优先显示,箭头被 SDK 忽略(仅虚线,无箭头)

这是腾讯 Android / iOS SDK 各自的渲染选择,插件层无法统一行为。

推荐用法:在同一条 polyline 上不同时使用箭头和虚线。如需"分段表达方向 + 间断",建议用两条独立 polyline 叠加,或使用 segmentColors 实现不同语义。


声明式更新

基本原理

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

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

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

final Map<String, Polyline> _polylines = {};

// 添加
_polylines['p1'] = Polyline(
  id: 'p1',
  points: const [LatLng(39.90, 116.39), LatLng(39.92, 116.41)],
  color: const Color(0xFF2196F3),
  width: 8,
);

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

// 追加点位(points 是 List,必须创建新 List)
_polylines['p1'] = _polylines['p1']!.copyWith(
  points: [..._polylines['p1']!.points, const LatLng(39.94, 116.43)],
);

// 删除
_polylines.remove('p1');

// 传入 Widget
TencentMap(polylines: Set<Polyline>.of(_polylines.values));

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

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

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

注意lineTypelineCaptextureLineTypearrowTexturearrowSpacingsegmentStylessegmentColorsgradient 的变更会触发折线重建(remove + re-add),插件层已自动处理。

本页内容