Skip to content

底图与地形管理

底图(BaseMap)和地形(Terrain)是三维地理场景的两大基础设施。BaseMapManager 管理 Cesium 的 ImageryLayerCollection,支持多底图叠加、排序、透明度调节和场景持久化;TerrainManager 管理 terrainProvider,支持预设地形和自定义地形服务切换。


BaseMapManager

概述

BaseMapManager 封装了对 viewer.imageryLayers 的操作,提供底图的增删改查、显示隐藏、透明度调节、层级排序以及事件通知能力。

构造函数

ts
constructor(viewer: Cesium.Viewer, options?: BaseMapManagerOptions)
参数类型说明
viewerCesium.ViewerCesium Viewer 实例
options.initialBaseMapBaseMapAddConfig(可选)初始化时自动添加的默认底图

类型定义

BaseMapAddConfig

ts
interface BaseMapAddConfig {
  name: string               // 底图名称
  config: BaseLayerConfig    // 底图配置
  token?: string             // API Token(天地图等需要)
  opacity?: number           // 初始透明度 (0-1)
  index?: number             // 插入层级位置
}

BaseLayerConfig 可以是预设类型字符串或自定义配置对象:

  • 预设类型'osm' | 'openstreetmap' | 'gaode' | 'gaode-img' | 'gaode-vec' | 'none'
  • 自定义类型对象
ts
interface CustomBaseLayerConfig {
  type: 'xyz' | 'wms' | 'arcgis' | 'single'
  url: string
  layers?: string       // WMS 图层名称
  maximumLevel?: number
  minimumLevel?: number
  tileWidth?: number
  tileHeight?: number
  subdomains?: string[]
  credit?: string
  [key: string]: any
}

BaseMapItem(运行时状态)

ts
interface BaseMapItem {
  id: string
  name: string
  type: 'preset' | 'custom'
  config: PresetBaseLayerType | CustomBaseLayerConfig
  opacity: number        // 透明度 (0-1)
  visible: boolean       // 是否可见
  index: number          // 层级位置
  imageryLayer: ImageryLayer   // 原生 Cesium 图层
  provider: ImageryProvider    // 原生 Cesium Provider
}

BaseMapSnapshot(可序列化快照)

ts
interface BaseMapSnapshot {
  id: string
  name: string
  type: 'preset' | 'custom'
  config: PresetBaseLayerType | CustomBaseLayerConfig
  opacity: number
  visible: boolean
  index: number
}

方法

底图操作

方法返回说明
addBaseMap(config)Promise<BaseMapItem>添加底图
removeBaseMap(id)boolean删除指定底图
removeAll()void删除所有底图

查询

方法返回说明
getBaseMap(id)BaseMapItem | undefined获取指定底图
getAllBaseMaps()BaseMapItem[]获取所有底图(按层级排序)

显示 / 隐藏

方法返回说明
show(id)void显示底图
hide(id)void隐藏底图
toggle(id)void切换显隐

透明度

方法返回说明
setOpacity(id, alpha)void设置透明度 (0-1)

层级排序

方法返回说明
raise(id)void上移一层
lower(id)void下移一层
raiseToTop(id)void移至顶层
lowerToBottom(id)void移到底层
moveTo(id, targetIndex)void移动到指定索引

场景持久化

方法返回说明
takeSnapshot()BaseMapSnapshot[]导出当前全部底图为可序列化快照
restoreFromSnapshot(snapshots)Promise<void>从快照恢复底图(清除现有后重建)

事件

ts
on(event: 'add' | 'remove' | 'visibility' | 'opacity' | 'order', callback): () => void

返回取消订阅函数。回调接收 BaseMapEvent

ts
interface BaseMapEvent {
  type: BaseMapEventType
  item: BaseMapItem
  previousIndex?: number   // type 为 'order' 时携带
}

销毁

方法返回说明
destroy()void销毁管理器,移除所有底图并清理事件监听

完整示例

ts
import { BaseMapManager } from '@space-air/gis-cesium'

const bm = new BaseMapManager(viewer)

// ---- 添加底图 ----

// 预设底图:OSM
const osm = await bm.addBaseMap({
  name: 'OpenStreetMap',
  config: 'osm',
  opacity: 1.0,
})

// 预设底图:高德影像
const gaode = await bm.addBaseMap({
  name: '高德影像',
  config: 'gaode-img',
})

// 自定义 XYZ 瓦片
const custom = await bm.addBaseMap({
  name: '自定义瓦片',
  config: {
    type: 'xyz',
    url: 'https://example.com/{z}/{x}/{y}.png',
  },
})

// 自定义 WMS
const wms = await bm.addBaseMap({
  name: 'WMS 服务',
  config: {
    type: 'wms',
    url: 'https://example.com/wms',
    layers: 'layer_name',
  },
})

// ---- 切换显示 ----
bm.hide(osm.id)
bm.show(osm.id)
bm.toggle(osm.id)

// ---- 透明度 ----
bm.setOpacity(osm.id, 0.5)

// ---- 排序 ----
bm.raiseToTop(gaode.id)
bm.lowerToBottom(osm.id)
bm.moveTo(custom.id, 1)        // 移动到索引 1

// ---- 事件监听 ----
const unsubscribe = bm.on('visibility', (e) => {
  console.log(`底图 ${e.item.name} 可见性: ${e.item.visible}`)
})

// ---- 场景持久化 ----
// 保存
const snapshot = bm.takeSnapshot()

// 恢复
await bm.restoreFromSnapshot(snapshot)

// ---- 清理 ----
bm.removeAll()       // 移除所有底图
bm.destroy()         // 销毁管理器

TerrainManager

概述

TerrainManager 管理 Cesium Viewer 的 terrainProvider。由于 Cesium 同一时间只能有一个活跃地形,管理器维护地形列表,通过 show(id) 切换不同地形。销毁时恢复默认地形 provider。

构造函数

ts
constructor(viewer: Cesium.Viewer, options?: TerrainManagerOptions)
参数类型说明
viewerCesium.ViewerCesium Viewer 实例
options.initialTerrainTerrainAddConfig(可选)初始化时自动添加的默认地形

类型定义

预设地形类型

ts
type PresetTerrainType = 'cesium-world' | 'none'
  • 'cesium-world':Cesium World Terrain(基于 Ion Asset ID 1,含地形光照和水面遮罩)
  • 'none':使用 EllipsoidTerrainProvider(无地形,平滑椭球面)

自定义地形配置

ts
interface CustomTerrainConfig {
  type: 'custom-url'
  url: string                           // terrain tileset URL
  requestVertexNormals?: boolean        // 请求地形光照,默认 true
  requestWaterMask?: boolean            // 请求水面遮罩,默认 false
}

TerrainAddConfig

ts
interface TerrainAddConfig {
  name: string
  config: PresetTerrainType | CustomTerrainConfig
}

TerrainItem

ts
interface TerrainItem {
  id: string
  name: string
  type: 'preset' | 'custom'
  config: PresetTerrainType | CustomTerrainConfig
  visible: boolean
  provider: TerrainProvider
}

TerrainSnapshot

ts
interface TerrainSnapshot {
  id: string
  name: string
  type: 'preset' | 'custom'
  config: PresetTerrainType | CustomTerrainConfig
  visible: boolean
}

方法

地形操作

方法返回说明
addTerrain(config, name?)Promise<TerrainItem>添加地形配置。config 可以是 TerrainAddConfig、预设字符串或 CustomTerrainConfig
removeTerrain(id)boolean删除指定地形。若为当前活跃地形,自动切换到下一个可用地形或回退到默认 provider
removeAll()void删除所有地形

查询

方法返回说明
getTerrain(id)TerrainItem | undefined获取指定地形
getAllTerrains()TerrainItem[]获取所有地形
getActiveTerrain()TerrainItem | undefined获取当前活跃地形

激活 / 切换

方法返回说明
show(id)void激活指定地形(切换 terrainProvider),触发 'switch' 事件

场景持久化

方法返回说明
takeSnapshot()TerrainSnapshot[]导出所有地形为可序列化快照
restoreFromSnapshot(snapshots)Promise<void>从快照恢复地形

事件

ts
on(event: 'add' | 'remove' | 'switch', callback): () => void

回调接收 TerrainEvent

ts
interface TerrainEvent {
  type: TerrainEventType
  item: TerrainItem
  previousItem?: TerrainItem   // 'switch' 事件时携带前一个活跃地形
}

销毁

方法返回说明
destroy()void销毁管理器,恢复默认 terrain provider,清理所有状态

完整示例

ts
import { TerrainManager } from '@space-air/gis-cesium'

const tm = new TerrainManager(viewer)

// ---- 添加地形 ----

// 预设:Cesium World Terrain
const world = await tm.addTerrain({
  name: 'Cesium World',
  config: 'cesium-world',
})

// 预设:无地形
const none = await tm.addTerrain({
  name: '无地形',
  config: 'none',
})

// 自定义地形服务
const custom = await tm.addTerrain({
  name: '自建地形',
  config: {
    type: 'custom-url',
    url: 'https://example.com/terrain/{z}/{x}/{y}.terrain',
    requestVertexNormals: true,
    requestWaterMask: true,
  },
})

// 快捷方式:传入 config + name 参数
await tm.addTerrain('cesium-world', 'Cesium World Terrain')
await tm.addTerrain({
  url: 'https://example.com/terrain/{z}/{x}/{y}.terrain',
  requestVertexNormals: true,
})

// ---- 切换地形 ----
tm.show(world.id)          // 激活 Cesium World Terrain

// 查询活跃地形
const active = tm.getActiveTerrain()
console.log(active?.name)  // "Cesium World"

// ---- 事件监听 ----
const unsubscribe = tm.on('switch', (e) => {
  console.log(`地形切换: ${e.previousItem?.name} -> ${e.item.name}`)
})

// ---- 场景持久化 ----
const snapshot = tm.takeSnapshot()     // 保存
await tm.restoreFromSnapshot(snapshot) // 恢复

// ---- 清理 ----
tm.removeAll()
tm.destroy()

快照 / 恢复模式

BaseMapManagerTerrainManager 都支持 takeSnapshot() + restoreFromSnapshot() 模式,方便将场景状态序列化存入文件,之后完整恢复。

ts
// 保存场景
const scene = {
  basemaps: bm.takeSnapshot(),
  terrains: tm.takeSnapshot(),
}

// 将场景序列化为 JSON 持久化
localStorage.setItem('scene', JSON.stringify(scene))

// 恢复场景
const saved = JSON.parse(localStorage.getItem('scene')!)
await bm.restoreFromSnapshot(saved.basemaps)
await tm.restoreFromSnapshot(saved.terrains)

注意restoreFromSnapshot 会先调用 removeAll() 清除当前状态,再根据快照重建。TerrainManager 恢复时会根据 visible 字段自动激活地形。