WholeProcessPlatform/frontend/docs/地图模块-抽吸规则与参数说明.md
2026-07-01 08:48:39 +08:00

8.6 KiB
Raw Blame History

地图模块-抽吸规则与参数说明

1. 文档目的

本文档用于记录当前地图点位“抽吸”功能的现行实现、默认参数、分层级显示规则和后续调参方式。
本文件描述的是当前已经落地并验证通过的规则,适合作为后续维护和继续调参的依据。

相关文档:

  • docs/地图模块-详细说明.md:地图整体架构说明
  • docs/地图模块-OpenLayers抽吸与碰撞分析.md:问题成因与改造分析

2. 当前实现范围

当前抽吸逻辑运行在 OpenLayers 主链路中,核心文件如下:

  1. src/modules/map/domain/nearby-point-rules.ts
  2. src/store/modules/map.ts
  3. src/components/gis/map.ol.ts
  4. src/components/gis/ol/point-layer-manager.ts

各文件职责:

  • nearby-point-rules.ts
    • 近邻点规则入口
    • 自动识别配置入口
    • 近邻点运行时元数据挂载
  • map.ts
    • 点位数据加载完成后,统一触发近邻点分组和元数据写回
  • map.ol.ts
    • 决定某个点在当前缩放级别是否显示
    • 决定文字是否允许显示
    • 承担图标与文字的手工碰撞控制
  • point-layer-manager.ts
    • 负责展开阶段的几何偏移
    • 负责把同组点位按扇形/环形布局散开

3. 当前抽吸规则

3.1 近邻点自动识别

当前采用自动识别近邻点,不再靠固定站名手工枚举。

识别原则:

  • 只在同一 layerKey 内做近邻识别
  • 按点位空间距离自动聚组
  • 满足最小组大小后,才认为是近邻组
  • 组内自动生成显示优先级 priority

这样做的目的:

  • 避免跨图层混组
  • 避免后续新增点位还要手工补名字
  • 让抽吸能力可以覆盖整批业务点

3.2 分层级显示规则

当前显示规则以 replaceAtZoomexpandAtZoom 为核心:

  1. zoom < replaceAtZoom
    • 只显示组内主点
    • priority = 1
  2. replaceAtZoom <= zoom < expandAtZoom
    • 显示组内前两个点
    • priority <= 2
    • 当前这样设计是为了避免主点在放大过程中突然消失
  3. zoom >= expandAtZoom
    • 同组点全部显示
    • 同时进入展开布局阶段

补充规则:

  • 如果某个点配置了 showZoomMinshowZoomMax,则先受这两个值约束
  • 没有进入近邻组的点,不受抽吸规则影响

3.3 文字显示规则

当前文字显示必须依赖点位显示。

也就是说:

  • 点不显示,文字一定不显示
  • 点显示后,文字还要继续通过碰撞判断才会显示

当前文字碰撞规则:

  • 文字要避让已保留的图标占位盒
  • 文字要避让已保留的其他文字
  • 图标与文字不再分别交给 OpenLayers 的 declutter 自动处理
  • 当前走的是项目内的手工碰撞控制

4. 当前默认参数

当前默认参数集中维护在:

  • src/modules/map/domain/nearby-point-rules.ts

当前采用统一配置对象:

type NearbyPointConfig = {
  autoRule: NearbyPointAutoRule;
  layoutRule: NearbyPointLayoutRule;
  densityDisplayRules: NearbyPointDensityDisplayRule[];
};

其中:

  • autoRule:控制近邻点自动识别、缩放切换和基础展开半径
  • layoutRule:控制展开阶段的单圈容量、扇形角度和外圈间距
  • densityDisplayRules:控制 distance 密度分档在不同缩放级别的基础显示资格

4.1 自动识别与缩放阶段参数

当前值如下:

参数 当前值 作用
distanceThresholdMeters 9000 近邻点自动识别距离阈值
replaceAtZoom 10.5 进入“主点 + 次点”阶段的缩放级别
expandAtZoom 12.2 进入“全部显示并展开”阶段的缩放级别
expandOffsetPx 48 第一圈展开的基础偏移半径
angleStepDeg 55 默认角度步长参考值
minGroupSize 2 最小成组数量

4.2 展开布局参数

当前值如下:

参数 当前值 作用
ringSize 5 单圈最多容纳的次点数量
fanAngleForTwoDeg 110 单圈剩余 2 个点时的扇形总角度
fanAngleForFourDeg 150 单圈剩余 34 个点时的扇形总角度
fanAngleForManyDeg 180 单圈剩余 5 个及以上点时的扇形总角度
ringGapPx 22 外圈最小增量半径
ringGapFactor 0.85 外圈相对基础半径的增量系数

4.3 密度分档显示参数

这里的 distance 不是物理距离,而是点位密度分档值。
数值越大表示越稀疏,越早参与显示候选;数值越小表示越密集,需要更高缩放级别才参与显示。

当前值如下:

minDensityValue minZoom 作用
1500000 0 很稀疏的点,从小缩放级别就可参与显示
800000 6.1 稍密集的点,从中低缩放开始参与显示
400000 8.1 中密度点,需要进一步放大
50000 10.6 高密度点,需要较高缩放级别
0 12.2 极密集点,只有更高缩放才进入候选

5. 当前展开布局

展开阶段由 point-layer-manager.ts 控制。

5.1 布局特点

当前布局不是简单把点随机散开,而是按以下方式处理:

  • 主点保留原位置
  • 同组其他点围绕主点展开
  • 展开方向优先偏下方
  • 单圈数量由 ringSize 控制
  • 点数较多时进入第二圈
  • 第二圈半径按 ringGapPxringGapFactor 继续增大,避免继续叠在一起

5.2 为什么优先向下展开

当前优先向下展开,主要是为了:

  • 尽量给上方文字留空间
  • 降低文字压住上方点的概率
  • 让地图上的抽吸形态更稳定

6. 当前实现的几个关键约束

6.1 不使用淡入淡出动画

目前已移除点和文字的淡入淡出动画。

原因:

  • 抽吸状态切换和动画叠加时,容易让点和文字出现闪烁
  • 会干扰对“当前到底该不该显示”的判断

当前阶段优先保证:

  • 显示规则稳定
  • 点和文字状态一致
  • 放大缩小时不出现明显错位

6.2 不再依赖 OL 的自动 declutter 决定图标命运

当前图标和文字都设置为 declutterMode: 'none',由项目内逻辑统一控制。

这样做的原因:

  • 避免图标和文字落在两套碰撞体系里
  • 避免出现“文字先出来、点没出来”
  • 避免文字压住其他点却仍然显示

7. 常见现象与调参建议

7.1 成组太少

表现:

  • 相近点仍然容易互相盖住
  • 进入展开前看起来还是压在一起

优先调整:

  • 增大 distanceThresholdMeters

7.2 成组太多

表现:

  • 距离并不算近的点也被当成一组
  • 放大后过早进入抽吸关系

优先调整:

  • 减小 distanceThresholdMeters

7.3 展开太晚

表现:

  • 放大到较深层级前仍然挤在一起

优先调整:

  • 减小 expandAtZoom

7.4 展开太早

表现:

  • 中等缩放时地图上就出现较明显散开效果

优先调整:

  • 增大 expandAtZoom

7.5 展开后间距不够

表现:

  • 虽然已经展开,但图标还是比较挤

优先调整:

  • 增大 expandOffsetPx
  • 或增大 ringGapPx
  • 或增大 ringGapFactor

7.6 单圈散开角度不合适

表现:

  • 次点虽然已经展开,但仍然集中在一侧
  • 或者扇形过大,展开形态显得太散

优先调整:

  • 调整 fanAngleForTwoDeg
  • 调整 fanAngleForFourDeg
  • 调整 fanAngleForManyDeg

7.7 主点在放大过程中突然消失

当前已经通过 replaceAtZoom <= zoom < expandAtZoom 阶段显示 priority <= 2 进行修正。
如果后续又出现类似现象,优先检查:

  • map.ol.tsshouldRenderNearbyFeature() 的阶段逻辑
  • 是否误改成只显示 priority = 2

7.8 明明周围看起来空,文字还是不显示

优先检查:

  • 图标碰撞盒是否过大
  • 文字碰撞盒是否过于保守
  • 候选集是否发生重复统计

相关代码主要在:

  • src/components/gis/map.ol.ts

8. 后续维护建议

建议后续继续保持以下约定:

  1. 抽吸参数继续统一放在 nearby-point-rules.ts
  2. 显示决策继续集中在 map.ol.ts
  3. 几何偏移继续集中在 point-layer-manager.ts
  4. 后续调参优先改 DEFAULT_NEARBY_POINT_CONFIG,不要直接把数值散落回业务代码
  5. 如果继续加动画,必须放在抽吸状态机完全稳定之后
  6. 如果继续优化 popup也要同步遵循“点先于文字”的显示原则

9. 当前结论

当前这版抽吸实现已经形成了比较稳定的主线:

  • 自动识别近邻点
  • 统一缩放阶段显示规则
  • 展开阶段几何偏移
  • 文字依赖点显示
  • 文字避让图标与文字

后续如果继续调优,建议先从参数层开始,不要先动主逻辑结构。