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>

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

相关推荐
王八八。5 小时前
nvm 安装与配置完全指南:从零到多版本 Node.js 自由切换
node.js
紫禁玄科6 小时前
Shai-Hulud:npm生态的自我复制蠕虫风暴
前端·npm·node.js
烂蜻蜓7 小时前
Node.js入门教程(十四):async/await
node.js
richdata11 小时前
动态OTB vs 静态OTB:鞋服零售该选哪种管理模式?
前端·html·零售
FungLeo16 小时前
Flutter Web 中文字体困境与渲染器选择:CanvasKit vs HTML renderer 实战
前端·flutter·html
gis开发之家17 小时前
《Vue3 从入门到大神50篇》Vue3 源码详解(二十):生命周期钩子源码解析 —— onMounted / onUpdated 如何实现?
前端·javascript·前端框架·vue3·vue3源码
3A Cloud19 小时前
从王虹的手写报告到可运行的 HTML 幻灯片:拆解 z-wanghong-handwritten-ppt
前端·人工智能·笔记·信息可视化·html·powerpoint·ppt
IMPYLH19 小时前
HTML 的 <embed> 元素
前端·数据库·html
必须会一定会19 小时前
用纯 HTML/JS 做一个 AI 需求澄清器:把模糊想法转换成可执行任务书
开发语言·前端·javascript·人工智能·html·ai编程
2401_881828322 天前
简易文本处理网页工具|AI 通识课第三次作业
前端·javascript·html