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>

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

相关推荐
C_心欲无痕2 小时前
nodejs - pnpm解决幽灵依赖
前端·缓存·npm·node.js
韩曙亮2 小时前
【Web APIs】移动端轮播图案例 ( 轮播图自动播放 | 设置无缝衔接滑动 | 手指滑动轮播图 | 完整代码示例 )
前端·javascript·css·html·轮播图·移动端·web apis
C_心欲无痕3 小时前
nodejs - npm serve
前端·npm·node.js
PieroPc3 小时前
Html +css+js 写的一个小商城系统(POS系统)
javascript·css·html
顾安r3 小时前
1.1 脚本网页 战推棋
java·前端·游戏·html·virtualenv
Irene19914 小时前
使用 Docker 的 Node.js(附:三种 Node.js 环境详细对比)
docker·容器·node.js
ChangYan.14 小时前
直接下载源码但是执行npm run compile后报错
前端·npm·node.js
Channing Lewis16 小时前
Python读取excel转成html,并且复制excel中单元格的颜色(字体或填充)
python·html·excel
cz追天之路17 小时前
华为机考 ------ 识别有效的IP地址和掩码并进行分类统计
javascript·华为·typescript·node.js·ecmascript·less·css3