Cesium学习第二章 camera 相机

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>

谢谢大家的阅读理解!写作不易,请大家点个赞在走哦~~

相关推荐
砚凝霜1 小时前
保姆级 | CTF Lemon:禁用右键/F12 怎么破?查看源码 + HTML 注释拿 flag
前端·html
普通人61 小时前
Web端3D模型加载实战指南_Vue3_uni-app_HTML
前端·javascript·uni-app·html
LuHang16 小时前
从天地图切换到高德地图:一次真实的底图迁移实战
前端·vue.js·cesium
Hone17 小时前
我把「自动发文章到掘金」做成了一个 Agent 技能:juejin-skills
node.js·ai编程·前端工程化
Dumbness1 天前
二十行手写的 SKILL.md 头部解析,遇到 YAML 的折叠写法、单引号和嵌套键就读错:和 js-yaml 逐条对照
node.js·ai编程
Frag0ut1 天前
Notepad++ 零基础入门:从记事本到代码编辑器的平滑过渡(2026最新版)
python·编辑器·html·json·notepad++·markdown·记事本
总要学点什么1 天前
第92篇:三维特效-圆(逐渐消逝)——从圆心开始,让一个洞把整片光啃到只剩外圈
gis·webgl·cesium·空间分析·1024程序员节
用户298698530141 天前
Python 实现 HTML 转纯文本:两种场景下的文档模型方案
python·html·api
前端架构师-老李1 天前
HTML与CSS基础第七课—HTML 中的a标签(跳转链接)
前端·css·html
总要学点什么1 天前
第89篇:三维特效-螺旋圆效果——让螺旋臂卷起一圈圈外扩的涟漪
开发语言·javascript·ecmascript·webgl·cesium·空间分析·1024程序员节