Appearance
相机书签(视点收藏 / 恢复)
把当前相机视角(世界坐标 + heading/pitch/roll,可选同步捕获场景缩略图)保存为书签, 之后按 id 用
camera.flyTo(平滑飞行)或camera.setView(瞬移)恢复视角。 对齐源案例Scene/BookMark:源实现把书签列表放在 React state 里,本能力把 「保存 / 恢复 / 管理」下沉为viewer.bookMark扩展,列表面板属示例层编排,不入 SDK。
能力定位
viewerBookMarkMixin 适合:
- 场景收藏:操作者把有价值的观察视角存下来,随时飞回;
- 多视点切换:巡检/演示时在预设视点间往返;
- 视角分享:书签含完整相机方位,团队可按同一视角复盘。
保存的缩略图是尽力而为(scene.render() 后读 canvas,dataURL):渲染管线或画布不可读时 自动降级为 undefined,书签仍正常保存,不影响后续 flyTo/setView。
安装与挂载
ts
import { CesiumViewer, viewerBookMarkMixin } from '@nexa/gis-cesium'
const nexaGis = new CesiumViewer('container')
const viewer = nexaGis.viewer
// 安装相机书签扩展:viewer 上挂载 bookMark API
nexaGis.extend(viewerBookMarkMixin)
// 裸 viewer 等价写法:extendViewer(viewer, viewerBookMarkMixin)本能力是插件 mixin,通过
nexaGis.extend(...)(托管入口)或extendViewer(viewer, ...)(函数式入口)安装,二者共用同一实现,SDK 不在裸Cesium.Viewer上打补丁。
API
保存书签:add(options?)
ts
add(options?: BookMarkAddOptions): CameraBookMark
interface BookMarkAddOptions {
name?: string // 书签名称
captureThumbnail?: boolean // 是否同步捕获当前场景缩略图(默认 false)
}
interface CameraBookMark {
id: string // 唯一标识(时间戳 + 随机后缀,add 时生成)
name?: string // 书签名称
position: Cartesian3 // 保存时刻相机世界坐标
heading: number // 方位角(弧度)
pitch: number // 俯仰角(弧度)
roll: number // 翻滚角(弧度)
thumbnail?: string // 场景缩略图(dataURL;捕获失败则省略)
createdAt: JulianDate // 创建时刻
}恢复视角:flyTo(id, options?) / setView(id)
ts
flyTo(id: string, options?: { duration?: number }): void // camera.flyTo,平滑飞行
setView(id: string): void // camera.setView,瞬移未知 id 为空操作(不抛错)。flyTo 传 duration 控制飞行时长,缺省用 Cesium 默认。
管理:list() / remove(id) / clear() / destroy()
ts
list(): readonly CameraBookMark[] // 全部书签(浅拷贝,外部修改不影响内部)
remove(id: string): boolean // 删除书签,返回是否删除成功
clear(): void // 清空全部
destroy(): void // 清空并卸载(幂等)基础示例
ts
import { CesiumViewer, viewerBookMarkMixin } from '@nexa/gis-cesium'
const nexaGis = new CesiumViewer('container')
const viewer = nexaGis.viewer
nexaGis.extend(viewerBookMarkMixin)
// 保存当前视角(含缩略图)
const mark = viewer.bookMark.add({ name: '二环视点', captureThumbnail: true })
// 任意移动相机后,飞回书签视角(带 2s 平滑飞行)
viewer.bookMark.flyTo(mark.id, { duration: 2 })
// 或瞬移
viewer.bookMark.setView(mark.id)
// 管理
const all = viewer.bookMark.list() // 全部书签(浅拷贝)
viewer.bookMark.remove(mark.id) // 删除
viewer.bookMark.clear() // 清空进阶示例
- 多个视点往返:依次
add多本书签,按需flyTo任意一本; - 不捕获缩略图:
add({ name: '视点A' })→ 缩略图为undefined,书签仍可 flyTo; - 保存前校准视角:先
camera.setView或flyTo到目标观察点,再add({ captureThumbnail: true }), 缩略图即该视角画面。
生命周期与清理
ts
viewer.bookMark.destroy() // 清空书签并卸载(幂等)destroy()可重复调用,重复调用安全;- viewer 销毁(
viewer.destroy())时经销毁钩子自动清理书签; - 示例层面:书签列表面板由示例代码自建 DOM 挂到容器内,切换/重置示例时随容器清空, 无需额外销毁计时器。
实现说明
- 快照:
add时读取camera.positionWC(克隆)+heading/pitch/roll(?? 0兜底), 生成id为Date.now().toString(36) + 随机后缀,createdAt为JulianDate.now(); - 缩略图:
captureThumbnail先scene.render()再同步读 canvastoDataURL('image/png')——同步读取避免依赖preserveDrawingBuffer,失败降级为undefined; - 恢复:
flyTo/setView用书签position为 destination、heading/pitch/roll为 orientation; - 资源所有权:mixin 只维护书签数组,不触碰任何 Entity/Primitive;uninstall 回调清空数组, 经
extendViewer注册为 viewer destroy 钩子(幂等去重)。
Cesium 版本限制
- 依赖 Cesium 公共
camera.positionWC/heading/pitch/roll、camera.flyTo/setView、scene.render、JulianDate,不使用私有 API; - 已验证目标版本:Cesium 1.133.1。
与原生 Cesium API 的组合方式
viewer.bookMark.add()等价于手动Cartesian3.clone(viewer.camera.positionWC)+ 读取相机方位,并把「列表管理 + 缩略图 + 按 id 恢复」收进一处;- 与
viewer.cameraControl(viewerCameraMixin)互不冲突:飞行定位能力在cameraControl, 视点收藏/恢复在bookMark,可同时挂载。