Skip to content

CesiumOLSync 二三维联动

viewerOverviewMapMixin双向联动增强:在原有 Cesium → OpenLayers 单向鹰眼图 基础上,新增 2D → 3D 反向联动 —— 拖动/缩放 OpenLayers 地图时,Cesium 相机跟随到 2D 视图中心与缩放级别。反向联动默认关闭,向后兼容原有用法。

能力定位

单向鹰眼图只回答「3D 相机在哪」;双向联动补上「2D 地图想让我看到哪」:

  • 2D 大屏选点:在二维地图上框选/漫游,3D 场景自动飞往对应区域;
  • 二三维对比漫游:操作任意一屏,另一屏同步跟随,适合指挥调度场景;
  • 鹰眼 + 反向:既看 3D 视域落在哪,又能从 2D 直接切走 3D 视角。

启用反向联动

OverviewMap 的安装参数上增加 reverse: true

ts
nexaGis.extend(viewerOverviewMapMixin, {
  map,
  ol: adapter,
  reverse: true, // 开启 2D→3D 反向联动
})
参数默认值说明
reversefalse2D 视图变化是否反向驱动 3D 相机

反向联动依赖 OpenLayers 的 map.on('moveend')view.getCenter()/getResolution();若 Map 不支持事件订阅,反向联动静默降级为单向, 不影响原有鹰眼图。

运行时 API

ts
viewer.overviewMap.setReverse(true)     // 运行时开启反向联动
viewer.overviewMap.setReverse(false)    // 运行时关闭
console.log(viewer.overviewMap.reverseEnabled) // 当前是否启用

setReverse 幂等且与 activate/deactivate 独立:deactivate() 暂停包括反向联动 在内的全部联动监听,恢复 activate() 时按 reverseEnabled 重挂。

反向联动实现要点

2D 视图移动完成后,插件读取 view.getCenter()(经纬度)与 view.getResolution() (度/像素),换算成相机高度后调用 camera.flyTo

ts
// EPSG:4326 世界视图分辨率约 0.07 → 高度约 210 万米;分辨率越小越接近地面
altitude = clamp(resolution * 30_000_000, 1_000, 2_500_000)
viewer.camera.flyTo({ destination: Cartesian3.fromDegrees(lon, lat, altitude) })

高度换算为经验近似,用于演示 2D → 3D 的跟随关系;业务场景可自行接管 moveend 完成精确姿态计算。

防止联动死循环:3D 相机变化会触发 sync() 把视域写回 2D,而 View.fit 又会触发 moveend。插件在 sync() 时记录写入的中心快照,onMoveEnd 命中该快照即视为自身回声 并忽略,从而切断「3D→2D→3D」的循环;反向驱动后相机变化产生的视域回写同样被抑制。

所有权与清理

OverviewMap 完全一致:mixin 只拥有视域 VectorLayer、 VectorSource 与 Cesium 相机/OL moveend 监听;OpenLayers Map 与底图由调用方拥有。 示例在 nexaGis.destroy 时同步释放自建的 OL Map(setTarget(undefined) + dispose)。

迁移说明

源案例在 2D 端使用在线天地图/高德瓦片。本示例改用 Canvas 生成的离线过程化世界概览图 (经纬网 + 抽象大陆轮廓),不复制来源不明的图片、不请求在线地图服务;案例用于演示 联动能力本身,而非瓦片加载。

验证命令

bash
pnpm --filter @nexa/gis-cesium run typecheck
pnpm --filter @nexa/gis-cesium run test
pnpm --filter @nexa/gis-cesium run build:lib
pnpm --filter @nexa/gis-cesium run check:governance
pnpm lint