外观
相机及视角
约 2229 字大约 7 分钟
2023-09-08
Camera相机控制了三维场景的视图。有很多方法可以操作Camera,如旋转(rotate)、缩放(zoom)、平移(pan)和飞到目的地(flyTo)。同时也有鼠标和触摸事件用来处理与Camera的交互,还有API来以编程方式操作摄像机。

1. map中视角相关设置和方法
我们在创建地图时,可以在scene的center参数中来设置默认视角,如:
const map = new mars3d.Map("mars3dContainer", {
scene: {
center: { lat: 25.389914, lng: 119.084961, alt: 1179575, heading: 346, pitch: -60 }
}
})当前map中与相机有关的方式:
| 方法名 | 说明 |
|---|---|
| map.getCameraView() | 可以获取当前视角 |
| map.setCameraView(cameraView, options) | 将相机本身定位至指定位置 |
| map.setCameraViewList(arr, enfun) | 定位到多个相机视角位置,按数组顺序播放 |
| map.flyHome() | 飞行到默认视角, 一般为config.json中的center参数配置的视角。 |
| map.flyTo(target, options) | 飞行定位至 Cesium相关矢量对象 处 |
| map.flyToGraphic(graphic, options) | 飞行定位至 Graphic矢量对象 处 |
| map.flyToExtent(extent, options) | 飞行定位至 矩形区域 处 |
| map.flyToPositions(positions, options) | 飞行定位至 坐标数组 处 |
| map.flyToPoint(point, options) | 视角中心定位至目标点(非相机位置) |
| map.cancelFlyTo() | 停止视角定位等操作 |
2. camera相机对象
map.camera 相机对象,由三维地图内部创建的Camera类, 描述了相机的当前状态,包括:位置(position),朝向( orientation), 参考空间( reference frame), 视锥体(view frustum).
一些最常用的方法如下:
- map.camera.setView(options): 在特定位置和方向立即设置相机。
- map.camera.zoomIn(amount): 沿着视角矢量移动摄像机。
- map.camera.zoomOut(amount): 沿视角矢量向后移动摄像机。
- map.camera.flyTo(options): 创建从当前相机位置到新位置的动画相机飞行。
- map.camera.lookAt(target, offset) : 定位并定位摄像机以给定偏移量瞄准目标点。
- map.camera.move(direction, amount) : 朝任何方向移动摄像机。
- map.camera.rotate(axis, angle) : 绕任意轴旋转相机。
使用setView函数设置Camera的位置和方向。destination可以是Cartesian3或Rectangle,orientation可以是heading/pitch/roll或direction/up。 heading航向角、pitch俯仰角和roll横滚角以弧度定义。
- heading航向角:是从正角度向东增加的局部北向旋转。
- pitch俯仰角:是指从局部的东北平面开始的旋转。正俯仰角在平面上方。负俯仰角在平面以下。
- roll横滚角:是围绕局部东轴应用的第一个旋转。
map.camera.setView({
destination: new Cesium.Cartesian3(x, y, z),
orientation: {
heading: headingAngle,
pitch: pitchAngle,
roll: rollAngle
}
})map.camera.setView({
destination: Cesium.Rectangle.fromDegrees(west, south, east, north),
orientation: {
heading: headingAngle,
pitch: pitchAngle,
roll: rollAngle
}
})上述的所有参数都是可选的。如果未指定,参数值将被设为默认值用户当前Camera的位置和方向。
2.1 平移位置
move* 和 zoom*方法,沿着相机方向或者某个给定向量来平移相机的位置,相机朝向不变。

2.2 旋转朝向
look* 和 twist* 方法,旋转相机朝向,向前向量(direction),向上向量(up),向右向量(right)都会改变,相机位置保持不变。
2.3 平移位置+旋转朝向
rotate* 方法,相对一个给定的向量,旋转相机的位置和朝向。
3. screenSpaceCameraController 鼠标相机控制器对象
map.scene.screenSpaceCameraController 是ScreenSpaceCameraController类 。 把屏幕画布上的用户输入(鼠标拖拽点击或者触摸事件)来修改相机的位置和方向。 它包含一些属性,可以启用/禁用某种用户输入,修改惯性、最小最大缩放距离等。
默认地,场景支持鼠标(电脑端)和手指触摸(移动端)交互,并且支持以下相机漫游方式:
| 鼠标操作 | 3D视图 | 2D视图 | 2.5D视图 |
|---|---|---|---|
| 左键 + 拖拽 | 旋转 | 平移 | 平移 |
| 右键 + 拖拽 | 缩放 | 缩放 | 缩放 |
| 中键滚轮 | 缩放 | 缩放 | 缩放 |
| 中键 + 拖拽 | 倾斜 | 无操作 | 倾斜地球 |
4. flyTo 飞行参数
第 1 节的一组 flyTo* 方法,第二个参数 options 均来自 Cesium 原生 Camera.flyTo 的选项(mars3d 的 flyToGraphic/flyToPoint 在其基础上扩展),常用项:
| 参数 | 说明 |
|---|---|
duration | 飞行时长(秒),默认 3;传 0 等同于立即定位 |
radius | 相机距目标的距离(米),flyToGraphic/flyToPoint 常用;也可用 scale 按包围球倍数缩放 |
minHeight / maxHeight | 定位后相机高度的最小/最大值,防止贴地太近或飞太高 |
heading / pitch / roll | 飞行结束后的朝向角(角度制,mars3d 封装层会转换;直接用 Cesium 的 camera.flyTo 时是弧度) |
maximumHeight | 飞行途中允许到达的最大高度,可以强制相机"抬高绕飞" |
complete / cancel | 飞行完成、被新的飞行打断时的回调 |
// 飞行到某个矢量,并指定结束姿态与回调
map.flyToGraphic(graphic, {
radius: 2000,
heading: 0,
pitch: -45,
duration: 3,
complete: () => {
console.log("飞行完成")
}
})
// 飞行中途需要立即停止(如用户手动操作了地图)
map.cancelFlyTo()注意:在 2.5D(ColumbusView)模式下设置
flyTo的pitch俯仰角不生效,这是 Cesium 自身的限制,需要倾斜视角时请切换到 3D 模式。更多框架集成中的相机问题见常见问题。
5. 视角约束与锁定
通过第 3 节的 screenSpaceCameraController 可以限制用户的操作范围,常用于交付型项目:
const controller = map.scene.screenSpaceCameraController
// 限制缩放距离(米),防止穿出地球或拉得过远
controller.minimumZoomDistance = 500
controller.maximumZoomDistance = 20000
// 禁止相机穿入地形/模型(默认开启,关闭后视角可以到地面以下)
controller.enableCollisionDetection = true
// 关闭某类操作:旋转、平移、缩放、倾斜、自由环视
controller.enableRotate = true
controller.enableTranslate = true
controller.enableZoom = true
controller.enableTilt = false
controller.enableLook = false
// 关闭惯性,松手即停
controller.inertiaSpin = 0
controller.inertiaTranslate = 0
controller.inertiaZoom = 0锁定正北(不允许倾斜和旋转):关闭倾斜与旋转后,再把朝向归 0。
map.scene.screenSpaceCameraController.enableTilt = false
map.setHeading(0)功能示例:限定视角范围基于 CameraHistory 实现,可限制视角矩形范围与高度区间,适合直接复用。
6. 跟随移动目标
map.trackedEntity 可以让相机持续跟随一个移动中的目标(车辆、飞机、人员),目标移动时视角中心自动同步,无需在每帧手动 flyToPoint:
// 跟随(目标需要是 Entity 体系的矢量,如 ModelEntity、PointEntity、BillboardEntity)
map.trackedEntity = graphic
// 取消跟随
map.trackedEntity = undefined说明:
- 只有内部基于 Cesium Entity 的 Graphic 可以直接赋值;纯 Primitive 类对象(如合并渲染对象)不支持,官方右键菜单中也是先判断
graphic.entity instanceof Cesium.Entity才显示"锁定"项。 - 跟随时仍可用鼠标环绕、缩放观察目标;需要"第一人称贴地"效果时使用 FirstPersonRoam 相机控制 thing。
- 角色(人/车)在场景中行走并联动视角,参考相机控制 thing:角色控制。
7. 多点飞行、巡航与漫游
| 需求 | 方案 |
|---|---|
| 按一组预设视点顺序飞行 | map.setCameraViewList(points, { complete }),每个视点支持 lng/lat/alt/heading/pitch/duration/stop,stop 为该点停留秒数。示例:视点飞行 |
| 开场动画(地球旋转放大入场) | map.openFlyAnimation(),示例:开场动画 |
| 地球自转 / 绕点旋转 | map.rotateAnimation();绕固定目标环绕用 RotatePoint,原地四周旋转用 RotateOut |
| 沿真实路线巡航、轨迹回放 | 使用 Route / FixedRoute 漫游路线 矢量,与时钟联动播放,原理见时钟 - 动画轨迹 |
| 第一人称贴地漫游、键盘漫游、街景操作习惯 | FirstPersonRoam、KeyboardRoam、街景操作习惯 |
| 自定义插值动画(复杂巡航轨迹) | 参考 tween 动画漫游,在每帧回调里 setCameraView |
// 视点巡航:每段的 duration 控制飞行秒数,stop 控制到达后停留秒数
const viewPoints = [
{ lng: 108.961601, lat: 34.217109, alt: 509.2, heading: 314.5, pitch: -22.5, duration: 6, stop: 0 },
{ lng: 108.96164, lat: 34.222159, alt: 510.3, heading: 211.2, pitch: -22.5, duration: 8, stop: 2 }
]
map.setCameraViewList(viewPoints, {
complete: () => {
console.log("巡航完成")
}
})8. 视角的保存与恢复
- map.getCameraView(isFormat) 返回当前视角的
{ lng, lat, alt, heading, pitch, roll },存入后端或 localStorage 即实现"视角书签";恢复时调用 map.setCameraView(cameraView, options)。完整示例:视角书签。 - 需要记录用户的每一步操作、支持上一步/下一步回退视角时,使用 CameraHistory 相机控制 thing,示例:视角历史记录。
- 更多相机控制类(旋转、环绕、漫游等)的清单见管理及分析功能 - 相机控制类。
