Skip to content

Viewer 初始化与生命周期

CesiumViewer 是对 Cesium 原生 Viewer 的业务封装类,负责三维地球视图的创建、时钟管理、实体 CRUD 以及销毁生命周期。

构造函数

typescript
constructor(container: HTMLElement | string, options?: CesiumViewerOptions)
参数类型必填说明
containerHTMLElement | stringDOM 元素或元素 ID。传入字符串时会通过 document.getElementById 查找
optionsCesiumViewerOptions初始化选项,见下方参数表

CesiumViewerOptions

以下为所有可用选项及其默认值:

选项类型默认值说明
animationbooleanfalse显示/隐藏动画控件
timelinebooleanfalse显示/隐藏时间轴
baseLayerPickerbooleanfalse显示/隐藏底图选择器
fullscreenButtonbooleanfalse显示/隐藏全屏按钮
vrButtonbooleanfalse显示/隐藏 VR 按钮
geocoderbooleanfalse显示/隐藏地理编码搜索框
homeButtonbooleanfalse显示/隐藏 Home 按钮
infoBoxbooleantrue显示/隐藏信息框
sceneModePickerbooleanfalse显示/隐藏场景模式切换(2D/3D/哥伦布视图)
selectionIndicatorbooleanfalse显示/隐藏选择指示器
navigationHelpButtonbooleanfalse显示/隐藏导航帮助按钮
navigationHelpVisiblebooleanfalse导航帮助面板初始可见性
sceneModeSceneModeSceneMode.SCENE3D初始场景模式
creditTextstring'🌍 AirGIS'左下角版权文字
baseLayerUrlstring内置单张底图默认底图图片 URL
defaultViewRectangle | { west, south, east, north }{ west: 70, south: 10, east: 140, north: 55 }默认相机视角(覆盖东亚)
viewFactornumber2视角包围盒缩放因子,控制相机距包围盒的距离比例
contextOptionsWebGLContextAttributes{ preserveDrawingBuffer: true }WebGL 上下文配置,默认启用 preserveDrawingBuffer 以支持截图
shouldAnimateboolean-是否自动播放时钟动画
terrainProviderTerrainProvider | false-地形 Provider
enableTerrainboolean-是否启用地形

NOTE

animationtimelinebaseLayerPicker 等控件默认值均为 false,以保持界面简洁,适合战术仿真场景。若需要标准 Cesium 界面,可自行启用。

WARNING

preserveDrawingBuffer: true 默认开启,这会影响 WebGL 性能(增加内存占用)。若不需要截图功能,可通过 contextOptions 覆盖该设置。

示例

typescript
import { CesiumViewer } from '@space-air/gis-cesium'
import { SceneMode } from 'cesium'

const viewer = new CesiumViewer('map', {
  animation: true,
  timeline: true,
  sceneMode: SceneMode.SCENE3D,
  defaultView: {
    west: 73,
    south: 3,
    east: 135,
    north: 53,
  },
  viewFactor: 1.5,
  creditText: 'SpaceAir GIS',
  contextOptions: {
    preserveDrawingBuffer: false,
    alpha: true,
  },
})

默认底图

CesiumViewer 在初始化时会自动加载一幅内置的单张世界影像图作为底图,底图覆盖全球范围(经度 -180 ~ 180,纬度 -90 ~ 90),分辨率为 5400 x 2700 像素。

typescript
// 构造函数内部实现的等效逻辑
const baseLayer = new ImageryLayer(
  new SingleTileImageryProvider({
    url: baseLayerUrl,         // 默认使用内置影像资源
    rectangle: Rectangle.fromDegrees(-180, -90, 180, 90),
    tileWidth: 5400,
    tileHeight: 2700,
  })
)

运行时底图切换由 BaseMapManager 接管,参见底图与地形指南。

默认相机视角

构造函数内部会修改 全局静态属性 Camera.DEFAULT_VIEW_RECTANGLECamera.DEFAULT_VIEW_FACTOR

typescript
Camera.DEFAULT_VIEW_RECTANGLE = rectangle  // 默认覆盖东亚区域
Camera.DEFAULT_VIEW_FACTOR = viewFactor    // 默认 2

参数对照

选项类型默认值
defaultView.westnumber70
defaultView.southnumber10
defaultView.eastnumber140
defaultView.northnumber55
viewFactornumber2

自定义视角

typescript
// 方式一:使用矩形对象
import { Rectangle } from 'cesium'

const viewer = new CesiumViewer('container', {
  defaultView: Rectangle.fromDegrees(110, 20, 130, 40),
  viewFactor: 3,
})

// 方式二:使用快捷对象
const viewer2 = new CesiumViewer('container', {
  defaultView: { west: 110, south: 20, east: 130, north: 40 },
})

CAUTION

Camera.DEFAULT_VIEW_RECTANGLE 是 Cesium 的全局静态属性,修改它会影响到同一页面中所有后续创建的 Camera 实例。如果你在同一页面中创建多个独立的 CesiumViewer,后创建的实例会覆盖前一个的默认视角。需要在创建前自行管理该副作用。

核心方法

getViewer()

返回原始 Cesium Viewer 实例,用于访问原生 API 或传给 Mixin:

typescript
const v = viewer.getViewer()
// v 的类型为 Cesium.Viewer

Clock 管理

setClock()

设置时钟参数:

typescript
interface ClockOptions {
  startTime?: Date | string | number   // 起始时间
  stopTime?: Date | string | number    // 结束时间
  currentTime?: Date | string | number // 当前时间
  clockRange?: ClockRange              // 循环方式
  multiplier?: number                  // 时间倍速
}

viewer.setClock({
  startTime: '2024-01-01T00:00:00Z',
  stopTime: '2024-01-02T00:00:00Z',
  currentTime: '2024-01-01T06:00:00Z',
  clockRange: ClockRange.LOOP_STOP,    // 循环播放
  multiplier: 60,                      // 60 倍速
})

ClockOptions 中时间字段支持以下类型,内部会自动转换:

  • Date 对象
  • ISO 8601 字符串(如 '2024-01-01T00:00:00Z'
  • Unix 时间戳(毫秒数)

getClock()

获取 Cesium Clock 实例,可直接操作:

typescript
const clock = viewer.getClock()
console.log(clock.currentTime)   // JulianDate
console.log(clock.multiplier)    // number

setClockRange()

仅设置循环方式,不修改其他时钟参数:

typescript
import { ClockRange } from 'cesium'

viewer.setClockRange({ clockRange: ClockRange.CLAMPED })

timelineZoomTo()

将时间轴视图缩放到指定区间(需要启用 timeline: true):

typescript
import { JulianDate } from 'cesium'

const start = JulianDate.fromIso8601('2024-01-01T00:00:00Z')
const stop = JulianDate.fromIso8601('2024-01-01T06:00:00Z')
viewer.timelineZoomTo(start, stop)

Entity CRUD

CesiumViewer 提供了对 viewer.entities 的快捷封装方法:

方法返回值说明
addEntity(entity)Entity添加一个 Entity 或普通对象
getEntity(id)Entity | undefined根据 ID 获取 Entity
getEntities()EntityCollection获取完整的 Entity 集合
removeId(id)boolean根据 ID 移除 Entity
removeEntity(entity)boolean移除指定的 Entity 实例
removeAllEntities()void移除所有 Entity
typescript
// 添加 Entity
const box = viewer.addEntity({
  id: 'demo-box',
  position: Cartesian3.fromDegrees(116.39, 39.91, 1000),
  box: {
    dimensions: new Cartesian3(4000, 4000, 4000),
    material: Color.RED.withAlpha(0.5),
  },
})

// 查找 Entity
const found = viewer.getEntity('demo-box')

// 遍历所有 Entity
const all = viewer.getEntities()
all.values.forEach(entity => console.log(entity.id))

// 移除 Entity
viewer.removeId('demo-box')
// 或 viewer.removeEntity(box)

// 清空所有
viewer.removeAllEntities()

TIP

addEntity() 接受 Entity 实例或普通对象,底层实际调用 viewer.entities.add()。如果需要更丰富的实体创建能力(带组件体系),请安装 viewerEntityMixin 并使用 createEntity()

销毁生命周期

当组件卸载或不再需要三维场景时,务必调用 destroy() 以释放 GPU 资源:

typescript
// 在 Vue 组件中
onBeforeUnmount(() => {
  viewer.destroy()
})

destroy() 内部会检查 viewer.isDestroyed(),避免重复销毁抛出异常:

typescript
destroy(): void {
  if (this.viewer && !this.viewer.isDestroyed()) {
    this.viewer.destroy()
  }
}

WARNING

调用 destroy() 后,CesiumViewer 实例及原始 Viewer 将不再可用。如需重新创建,请新建一个 CesiumViewer 实例。

完整示例

typescript
import { CesiumViewer } from '@space-air/gis-cesium'
import {
  Cartesian3,
  Color,
  ClockRange,
  JulianDate,
} from 'cesium'
import { onMounted, onBeforeUnmount } from 'vue'

let viewer: CesiumViewer

onMounted(() => {
  // 初始化
  viewer = new CesiumViewer('cesiumContainer', {
    animation: false,
    timeline: true,
    creditText: 'My App',
    defaultView: { west: 110, south: 20, east: 130, north: 40 },
  })

  // 设置时钟
  viewer.setClock({
    startTime: '2024-01-01T00:00:00Z',
    stopTime: '2024-01-01T12:00:00Z',
    currentTime: '2024-01-01T00:00:00Z',
    clockRange: ClockRange.LOOP_STOP,
    multiplier: 120,
  })

  // 添加 Entity
  viewer.addEntity({
    id: 'marker',
    position: Cartesian3.fromDegrees(116.39, 39.91, 500),
    point: {
      pixelSize: 10,
      color: Color.YELLOW,
    },
    label: {
      text: '北京',
      font: '14px sans-serif',
      fillColor: Color.WHITE,
    },
  })
})

onBeforeUnmount(() => {
  viewer?.destroy()
})

相关指南

  • 快速开始 — 从零搭建第一个三维场景
  • 相机控制 — 飞行漫游与视角锁定
  • 实体管理 — CombatEntity 组件体系
  • 底图与地形 — BaseMapManager / TerrainManager