地图渲染模块架构设计文档

1. 架构概述

本项目采用高吞吐量、低开销的增量渲染架构来处理海量船舶和航线的展示。为了避免 Vue 响应式系统在处理海量 DOM 节点时的性能瓶颈,地图渲染核心完全与 Vue 的视图模板解耦,采用原生 TypeScript + Leaflet API 结合状态机缓存的策略。

整个模块采用分层解耦的设计:

  1. 基础设施层 :hifleet-loader.ts 和 animation.ts(负责 SDK 异步加载与 requestAnimationFrame 防抖)。
  2. 状态控制层(适配器) :useHifleetMap.ts(桥接 Vue 生命周期与 Leaflet 实例)。
  3. 渲染引擎层(核心) :hifleet-map-voyage-renderer.ts 及其辅助文件(执行具体的增量 DOM 操作)。
  4. 组件展示层 :MapStage.vue(提供容器和事件抛出)。

2. 核心设计模式

2.1 增量更新与快照缓存 (Incremental Update & Snapshot Caching)

在 hifleet-map-voyage-renderer.ts 中,为每个航次维护了独立的 VoyageLayerState。每次渲染时,不会销毁重建图层,而是生成一组"快照签名 (Key)"与上一次比对:

  • renderedLineKey:包含了选中状态标识和轨迹坐标字符串。
  • renderedPointKey:包含了地图层级、选中状态和可视区域内的轨迹点。
  • renderedMarkerPositionKey:船舶经纬度字符串。
  • renderedMarkerIconKey:包含船名、颜色、航向、选中状态。

优势 :当航次属性未发生能导致视觉变化的改变时,直接 return 阻断 Leaflet DOM 操作,将性能损耗降至最低。

2.2 渲染风暴抑制 (Render Storm Coalescing)

地图的 zoom 和 pan 操作会在极短时间内触发成百上千次重绘事件。 在 animation.ts 中通过封装 requestAnimationFrame(即 createRafTask),确保在同一帧内,无论触发多少次渲染指令,都合并为一次执行。这在 useHifleetMap.ts 的 scheduleRefresh 函数中被完美应用。

2.3 实时数据的降级渲染 (Degraded Rendering for Realtime Data)

针对实时事件 VoyageRealtimeEvent:

  • 若收到 voyage.point (点事件) :意味着轨迹发生变化,调用全量的 updateVoyageLayer 重新计算轨迹线和点。
  • 若收到 voyage.snapshot (快照事件) :意味着仅仅是船舶移动或摘要数据变化,调用轻量的 updateVoyageMarker 仅更新图标位置和旋转角度,而不重算海量轨迹。

3. 模块职责边界

3.1 src/utils/map/hifleet-map-voyage-renderer.ts

职责 :单例工厂,闭包维护了所有的 layerStates(状态集)和 iconCache(图标缓存)。 核心流程:

  1. renderVoyages 接收全量数据,比对增删。
  2. 过滤掉离开地图视野的轨迹点。
  3. 调用 syncRouteLine、syncPointLayer 和 syncShipMarker 进行细粒度的 DOM diff。
  4. 提供 clear 方法在组件卸载时回收所有 Leaflet 内存。

3.2 src/utils/map/hifleet-map-icons.ts

职责 :纯函数集合,负责生成 Leaflet 所需的 HTML 字符串 (divIcon)。 设计考量:

  • 内部实现了 escapeHtml 以防御 XSS 注入。
  • 通过 CSS Variables (--ship-color, --ship-rotation) 将状态变化交由浏览器硬件加速处理,而不是每次重写 HTML。

3.3 src/utils/map/hifleet-map-rendering.ts

职责 :渲染辅助函数集。 设计考量 :将序列化逻辑 (serializeLatLng)、颜色计算 (getPointColor) 和图层销毁逻辑 (removeMissingVoyageLayers) 抽离,保持 renderer 主文件的纯净。

3.4 src/composables/useHifleetMap.ts

职责 :作为 Vue Store 和 Renderer 之间的适配器。 设计考量:

  • 隐式处理了 HiFleet SDK 特有的 changeMap 卫星图切换残留 Bug(引入 global 中间态)。
  • 监听 DOM 的 ResizeObserver 自动调用 invalidateSize。
  • 将 Leaflet 实例包裹在 shallowRef 中,防止 Vue 递归劫持 Leaflet 内部庞大而复杂的对象树,引发极端的性能问题。

4. 后续扩展与维护指南

4.1 新增渲染层

如果需要新增渲染图层(如:渲染所有的停靠港口),请不要 在现有的 hifleet-map-voyage-renderer.ts 中堆砌代码。应当参考该文件,新建一个 hifleet-map-port-renderer.ts,然后在 useHifleetMap.ts 中实例化它。保持不同业务实体的渲染器相互独立。

4.2 缓存键 (Cache Key) 维护

如果未来 VoyageSummary 新增了影响 UI 的属性(例如:根据吃水深度改变线条粗细),必须同步更新对应函数的 Key 生成逻辑。 例如:修改 syncRouteLine 中的 lineKey,加入吃水深度变量。否则图层将不会响应数据变化。

4.3 图标内存泄漏防护

目前图标采用了 Map 进行字符串级的单例缓存。如果未来产生了极度分散的变量(如每艘船都有完全不重复且无限生成的渐变色),可能导致 iconCache 内存无限膨胀。此时需引入 LRU (Least Recently Used) 算法或定期清理策略。

相关推荐
qq_4523962312 小时前
第十四篇:《Codex 源码拆解:137 个 crate 构成的智能体架构》
架构
MobotStone12 小时前
做了几个 Agent 项目后,我发现:真正拉开 AI 产品经理差距的,不是技术
人工智能·架构
IT大白鼠13 小时前
DeepSeek Harness 详解开源插件化 AI Agent 运行时:架构、模式、安装与生态
人工智能·架构·开源
这个DBA有点耶15 小时前
数据库双轨并行实战:全量并行策略、增量延迟控制、双向回切与一致性校验
数据库·架构·dba
Gl�ria15 小时前
MySQL 单机版 vs 高可用版:宕机排查 + 故障处理
mysql·adb·架构
Devlive 开源社区16 小时前
KnowForge 2026.0.8 发布:协作写作、团队空间、AI 朗读,这次更新有点大
架构
53488736abcdefg16 小时前
Hive 入门&架构原理
hive·hadoop·架构
一条大祥脚16 小时前
【CS336】lecture5 GPU|算力缩放|架构|内存模型|执行模型|TPU
架构
吴建旭 智宅焕17 小时前
智能家居B端交付能力解耦架构:从全链路自持到全国交付基础设施接入
架构·智能家居
fundoit17 小时前
为什么需要 Access Token 和 ID Token 两个令牌
java·spring·架构·github·oauth2