camera:照相机,也就是我们所说的设置中心点,让我们打开应用的时候,视角直接对着我们设置的地方。
不设置中心点的时候打开应用默认是整个地球

这就有点太大了。设置相机让他飞到北京天安门,让我们打开应用直接就能俯瞰天安门(可能因为国家安全原因或者性能原因地图里面的建筑都是方块模型,不过别担心,后面我们会学习如何把方块建筑替换成我们需要的建筑模型)

俯瞰天安门。

好了,要实现上面的效果。我们要先简单了解一下今天所用的东西都是什么意思。
javascript
import {
Cartesian3,
createOsmBuildingsAsync, // 创建全球3D建筑物调用方法: awati createOsmBuildingsAsync()
Ion, // 目前仅有它来 设置我们申请的tokens Ion.defaultAccessToken = 'your_tokens'
Math as CesiumMath,
Terrain,
Viewer,
} from 'cesium'
坐标转换(Cesium 开发核心场景)
Cartesian3 类用于表示三维笛卡尔坐标系(x, y, z)中的点或向量,是 Cesium 中最核心的几何类之一,广泛应用于位置表示、向量计算、坐标转换等场景(如相机位置、实体位置、方向向量等)。
javascript
Cartesian3.fromDegrees(longitude, latitude, height, ellipsoid, result)
fromDegrees(longitude, latitude, height, ellipsoid, result)
描述:将经纬度高度(WGS84 大地坐标) 转换为笛卡尔坐标(世界坐标系,ECEF)
参数:
longitude:经度(度)
latitude:纬度(度)
height:高度(米,默认 0.0)
ellipsoid:参考椭球体(默认 Ellipsoid.WGS84)
result:可选,存储结果的 Cartesian3 实例(避免重复创建对象)
返回值:转换后的笛卡尔坐标(Cartesian3)
它的用法是以下代码:
javascript
// 北京天安门位置(高度设为 500 米,便于视角观察)
const beijingPosition = Cartesian3.fromDegrees(116.39126, 39.9034, 500)
如上 就是把我们熟知的经纬度高度,转换为世界坐标系。
下面的代码就是我们说的设置中心点,让相机飞到我们要去看的地方北京天安门。
javascript
// 让相机飞行到北京天安门指定的经度、纬度和高度位置
viewer.camera.flyTo({
destination: beijingPosition, // 北京天安门坐标
orientation: {
heading: CesiumMath.toRadians(0.0), // 方向角(0 表示正北)
pitch: CesiumMath.toRadians(-15.0), // 俯仰角(负值表示向下看)
},
})
下面是本示例的完整代码。复制在vue3中可以直接运行,前提是你需要完成第一章的插件安装。
(二次编辑增加了返回地球、飞去天安门、缩放、旋转、停止旋转等按钮)
html
<script setup lang="ts">
import { onMounted } from 'vue'
import {
Cartesian3,
createOsmBuildingsAsync,
Ion,
Math as CesiumMath,
Terrain,
Viewer,
SceneMode,
HeadingPitchRange,
} from 'cesium'
import 'cesium/Build/Cesium/Widgets/widgets.css'
let viewer: Viewer | null = null
// 北京天安门位置(高度设为 500 米,便于视角观察)
const beijingPosition = Cartesian3.fromDegrees(116.39126, 39.9034, 500)
// Cartesian3 类用于表示三维笛卡尔坐标系(x, y, z)中的点或向量,是 Cesium 中最核心的几何类之一,广泛应用于位置表示、向量计算、坐标转换等场景(如相机位置、实体位置、方向向量等)。
// 坐标转换(Cesium 开发核心场景)
// fromDegrees(longitude, latitude, height, ellipsoid, result)
// 描述:将经纬度高度(WGS84 大地坐标) 转换为笛卡尔坐标(世界坐标系,ECEF)
// 参数:
// longitude:经度(度)
// latitude:纬度(度)
// height:高度(米,默认 0.0)
// ellipsoid:参考椭球体(默认 Ellipsoid.WGS84)
// result:可选,存储结果的 Cartesian3 实例(避免重复创建对象)
// 返回值:转换后的笛卡尔坐标(Cartesian3)
// 让相机飞行到北京天安门指定的经度、纬度和高度位置
const handleflyto = () => {
if (!viewer || !beijingPosition) {
console.warn('Viewer or Beijing position not initialized')
return
}
viewer.camera.flyTo({
destination: beijingPosition, // 北京天安门坐标
orientation: {
heading: CesiumMath.toRadians(0.0), // 方向角(0 表示正北)
pitch: CesiumMath.toRadians(-15.0), // 俯仰角(负值表示向下看)
},
})
}
const resetView = () => {
if (!viewer) {
console.warn('Viewer position not initialized')
return
}
viewer.camera.setView({
destination: Cartesian3.fromDegrees(105, 25, 100000000),
})
viewer.scene.mode = SceneMode.SCENE3D
}
// 放大
const handleZoomIn = () => {
if (!viewer) {
console.warn('Viewer position not initialized')
return
}
viewer.camera.zoomIn(400)
}
// 缩小
const handleZoomOut = () => {
if (!viewer) {
console.warn('Viewer position not initialized')
return
}
viewer.camera.zoomOut(400)
}
let rotate: number
// 相机环绕目标点旋转(每帧旋转 0.5°)
const rotateAroundTarget = () => {
if (!viewer) {
console.warn('Viewer position not initialized')
return
}
viewer.camera.lookAt(
beijingPosition,
new HeadingPitchRange(
viewer.camera.heading + CesiumMath.toRadians(0.1), // 每次增加 0.5° 朝向角
CesiumMath.toRadians(-30), // 固定俯仰角
1000, // 固定距离
),
)
rotate = requestAnimationFrame(rotateAroundTarget) // 循环执行
}
const stopRotate = () => {
cancelAnimationFrame(rotate)
}
onMounted(async () => {
Ion.defaultAccessToken =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI1ODQ5MDM2MS0xY2JmLTRhYmUtODYyZC1iNDViMzk2ZDdkZGUiLCJpZCI6MzczNjc0LCJpYXQiOjE3NjcwODE3NjV9.LuYkwE7AwGf01zlwLT9GOo2h5oERVIayz5F0nXwoxAU'
// 在 ID 为 cesiumContainer 的 HTML 元素中初始化 Cesium 视图器
viewer = new Viewer('cesiumContainer', {
terrain: Terrain.fromWorldTerrain(), // 加载全球地形 此处若不加载地形,会导致有些3D建筑 下面是悬空的
})
// 添加全球 3D 建筑物图层(Cesium OSM Buildings)
const buildingTileset = await createOsmBuildingsAsync()
viewer.scene.primitives.add(buildingTileset)
})
</script>
<template>
<main>
<div class="box">
<div id="cesiumContainer"></div>
<div class="btns">
<el-button @click="handleflyto">飞到北京天安门</el-button>
<el-button @click="resetView">重回地球</el-button>
<el-button @click="handleZoomIn">放大</el-button>
<el-button @click="handleZoomOut">缩小</el-button>
<el-button @click="rotateAroundTarget">开始环绕</el-button>
<el-button @click="stopRotate">停止环绕</el-button>
</div>
</div>
</main>
</template>
<style scoped>
.box {
position: relative;
}
.btns {
width: 100%;
position: absolute;
top: 0;
left: 0;
right: 0;
}
</style>