Skip to content

ViewerSync 双屏相机同步

让两个 Cesium Viewer 的相机联动:以 on(host) 的 host 与 options.target 组成联动对, 主控 Viewer 每次渲染后把其 position/heading/pitch/roll 通过公共 camera.setView 复制到 从属 Viewer,实现实时同步。


能力定位

ViewerSync 适合:

  • 双屏对比:同一场景左右分屏,操作一边另一边实时跟随,直观对比视角;
  • 大屏联动:主视角 + 从属视角同时呈现,主控操作统一所有屏;
  • 多窗口监控台:二三维 / 多窗口的相机统一,从一个屏控制全部。

CameraBoundary(被动约束)不同:ViewerSync主动联动——主控相机每次移动都会 驱动从属相机,二者可组合使用(约束主控屏范围,其余屏跟随)。

构造函数

ts
constructor(options: ViewerSyncOptions)
ts
interface ViewerSyncOptions {
  target: Viewer          // 必填:与 host 构成联动对的另一 Viewer
  mode?: ViewerSyncMode   // 同步模式,默认 'hover'
}
参数类型默认值描述
targetViewer(必填)on(host) 的 host 组成联动对的另一 Viewer
mode'hover' | 'a-to-b' | 'b-to-a''hover'主从判定方式

主从模式(mode)

模式主控说明
hover(默认)鼠标悬停所在 Viewer鼠标移到哪屏,哪屏主控,另一屏跟随
a-to-bhost固定 host 主控,target 跟随
b-to-atarget固定 target 主控,host 跟随

注意mode 在构造后只读。需要运行时切换模式时,destroy 旧实例并按新模式重建 (参考示例代码的「模式切换」按钮做法)。

生命周期

实现 Lifecycle<Viewer> 契约,on/off/destroy 均幂等:

ts
on(viewer: Viewer): void      // 绑定两个 Viewer 的 scene.postRender 与容器 mouseenter
off(viewer: Viewer): void     // 移除全部监听(幂等,可再次 on)
destroy(viewer: Viewer): void // 等价于 off + 置空 target 引用

清理完整性:本类只拥有两个 Viewer 的 postRender 监听与容器 mouseenter 处理器, off/destroy 全部移除并置空引用,不触碰调用方相机与其他资源。

基础示例

ts
import { ViewerSync } from '@nexa/gis-cesium'

// viewer1 为 host,viewer2 为 target,默认 hover 模式
const sync = new ViewerSync({ target: viewer2 })
sync.on(viewer1) // 开启:鼠标所在 Viewer 为主控,另一个跟随

// 页面或场景退出时统一销毁(幂等)
sync.destroy(viewer1)

进阶示例

固定主从 + 运行时切换模式:

ts
import { ViewerSync } from '@nexa/gis-cesium'

let sync = new ViewerSync({ target: viewer2, mode: 'a-to-b' })
sync.on(viewer1) // 固定 viewer1 主控,viewer2 跟随

// 切换为 b-to-a:mode 构造后只读,需重建
sync.destroy(viewer1)
sync = new ViewerSync({ target: viewer2, mode: 'b-to-a' })
sync.on(viewer1) // 固定 viewer2 主控,viewer1 跟随

实现说明

  • 同步时机:分别监听两个 Viewer 的 scene.postRender(每帧渲染回调),按主从判定复制相机, 实现真正的双向联动。
  • 源案例缺陷修复:源实现(Analysis/ViewerSync)仅监听 viewer1 的 postRender,当仅 viewer2 相机移动而 viewer1 静止时反向同步失效;本实现分别监听两个 Viewer 的 postRender 并按主从判定复制,修复该缺陷。
  • 防反馈循环:复制使用 dst.camera.setView 期间置 _syncing 重入保护,且主从判定保证 从属屏渲染不会反向驱动主控屏。
  • 公共 API:复制相机全部使用 Cesium 公共 camera.position/heading/pitch/roll/setView, 不触碰私有字段。
  • 无外部依赖:源案例的外网底图 / 初始飞行 / 隐藏 credit 等 demo 编排迁移时剥离, 使用 SDK 默认底图与示例区域视角。

清理责任

ts
sync.destroy(viewer1) // 或 sync.off(viewer1),等价且幂等

重复调用 destroy/off 安全(未 on 时为空操作)。销毁后重新 on 可再次启用同步。

Cesium 版本限制

  • 依赖 Cesium 公共 Camera.setView / position / heading / pitch / rollScene.postRender 事件、EventContainermouseenter
  • 已验证目标版本:Cesium 1.133.1。