Cesium从入门到入坟

大扎好,我系渣渣辉,斯一扔,介四里没有挽过的船新版本,挤需体验三番钟,里造会干我一样,爱象节款js裤

Cesium 概述

Cesium是国外一个基于JavaScript编写的使用WebGL的地图引擎,支持3D,2D,2.5D形式的地图展示,也是目前最流行的三维数字地球渲染引擎。

Cesium 基础介绍

首先我们需要登录上Cesium的官网,网址是 cesium.com/ ,获取源代码可以在Platform菜单项的Downloads中下载 。 接下来,第一个比较重要的事情就是我们需要注册一个免费账户以获取Cesium世界地形资产所需的访问令牌,而这个账户的token决定了哪些资产咱们可以使用;而第二个比较重要的事情就是Cesium的文档中心( cesium.com/learn/cesiu... ),我们在实际使用的过程中会经常来查阅这些API。

Cesium 的使用

由于我是使用的vue-cli生成的项目,所以直接安装vite-plugin-cesium依赖项,当然你也可以使用直接下载源码,在HTML中引入的方式。如果使用的是vite-plugin-cesium,你还需要在vite.config.ts中添加一下Cesium的引用。

js 复制代码
import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import VueDevTools from 'vite-plugin-vue-devtools'
// add this line
import cesium from 'vite-plugin-cesium';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    vueJsx(),
    VueDevTools(),
    // add this line
    cesium()
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

初始化地球

js 复制代码
<script setup lang="ts">
import { onMounted } from 'vue'
import * as Cesium from 'cesium'
onMounted(() => {
  const defaultToken = 'your access token'
  Cesium.Ion.defaultAccessToken = defaultToken
  const viewer = new Cesium.Viewer('cesiumContainer', {
    //这里是配置项
  })
})
</script>

<template>
  <div id="cesiumContainer" class="cesium-container"></div>
</template>

<style scoped>
#cesiumContainer {
  width: 100vw;
  height: 100vh;
}
</style>

效果如下:

现在我们就可以看到Cesium生成的地球了,可以对其进行二维和三维状态的切换,也可以用其自带的播放器,对时间轴进行一个播放,支持正放和倒放,Cesium还自带了搜索地理位置组件,并且兼容了中文。

Cesium 常用的类

1. Viewer

它是Cesium展示三维要素内容的主要窗口,不仅仅包含了三维地球的视窗,还包含了一些基础控件,在定义Viewer对象的时候需要设定基础部件、图层等的初始化状态,下面演示一下部分属性的使用。

js 复制代码
  const viewer = new Cesium.Viewer('cesiumContainer', {
    // 这里是配置项
    // 动画播放控件
    animation: false,
    // 时间轴控件
    timeline: false,
    // 全屏按钮
    fullscreenButton: true,
    // 搜索位置按钮
    geocoder: true,
    // 帮助按钮
    navigationHelpButton: false,
    // VR按钮
    vrButton: true
  })

除了上述的控件属性之外,还有entities这种实体合集属性,主要用于加载实体模型,几何图形并对其进行样式设置,动效修改等,我们可以通过下述代码生成一个绿色的圆点。

js 复制代码
const entity = viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 400),
  point: {
    pixelSize: 100,
    color: new Cesium.Color(0, 1, 0, 1)
  }
})
viewer.trackedEntity = entity

效果如下:

当然,我们也可以用entities来加载模型文件,下面我们用飞机模型试试

js 复制代码
  /** 通过entities加载一个飞机模型 */
  const orientation = Cesium.Transforms.headingPitchRollQuaternion(
    position,
    new Cesium.HeadingPitchRoll(-90, 0, 0)
  )
  const entity = viewer.entities.add({
    position: position,
    orientation: orientation,
    model: {
      uri: '/Cesium_Air.glb',
      minimumPixelSize: 100,
      maximumScale: 10000,
      show: true
    }
  })
  viewer.trackedEntity = entity

效果如下:

2. Camera

Cesium中可以通过相机来描述和操作场景的视角,而通过相机Camera操作场景的视角还有下面的几种方法

  • 飞行fly,比如flyTo,flyHome,flyToBoundingSphere
  • 缩放zoom,比如zoomIn,zoomOut
  • 移动move,比如moveBackward,moveDown,moveForward,moveLeft,moveRight,moveUp
  • 视角look,比如lookDown,lookLeft,lookRight,lookUp
  • 扭转twist,比如twistLeft,twistRight
  • 旋转rotate,比如rotateDown,rotateLeft,rotateRight,rotateUp
  • 其他方法,比如setView,lookAt
js 复制代码
viewer.scene.camera.setView({
    // 设定相机的目的地
    destination: position,
    // 设定相机视口的方向
    orientation: {
      // 控制视口方向的水平旋转,即沿着Y轴旋转
      heading: Cesium.Math.toRadians(0),
      // 控制视口方向的上下旋转,即沿着X轴旋转
      pitch: Cesium.Math.toRadians(-20),
      // 控制视口的翻转角度,即沿着Z轴旋转
      roll: 0
    }
})

我们尝试使用setView后可以发现,相机视角直接被定位到了下图的位置

3. DataSourceCollection

DataSourceCollection是Cesium中加载矢量数据的主要方式之一,它最大的特点是支持加载矢量数据集和外部文件的调用,主要有三种调用方法,分别为 CzmlDataSourceKmlDataSourceGeoJsonDataSource,分别对应加载Czml,Kml,GeoJSON格式的数据,在使用过程中我们只需要将矢量数据转换为以上任意一种格式就可以在Cesium中实现矢量数据的加载和存取。

js 复制代码
  viewer.dataSources.add(Cesium.GeoJsonDataSource.load('/ne_10m_us_states.topojson'))

效果如下: 这时候我们看到图层已经被加载上去了~

Cesium的坐标体系

通过上面的示例我们可以得知Cesium具有真实地理坐标的三维球体,但是用户是通过二维屏幕与Cesium进行操作的,假设我们需要将一个三维模型绘制到三维球体上,我们就需要再地理坐标和屏幕坐标之间做转换,而这就需要涉及到Cesium的坐标体系。

Cesium主要有5种坐标系:

  • WGS84经纬度坐标系
  • WGS84弧度坐标系
  • 笛卡尔空间直角坐标系
  • 平面坐标系
  • 4D笛卡尔坐标系

他们的基础概念大家感兴趣的可以百度查阅一下,我也说不太清楚,问我他们的区别我也只能用 恰特鸡屁踢 敷衍你,下面我们演示一下怎么将WGS84左边西转换为笛卡尔空间直角坐标系:

js 复制代码
const cartesian3 = Cesium.Cartesian3.fromDegrees(longitude, latitude, height)

我们可以通过经纬度进行转换,当然我们还有其他的方式,比如Cesium.Cartesian3.fromDegreesArray(coordinates),这里的coordinates格式为不带高度的数组。

Cesium加载地图和地形

加载地图

我们使用ArcGis地图服务来加载新地图,Cesium也给其提供了相关的加载方法:

js 复制代码
  const esri = await Cesium.ArcGisMapServerImageryProvider.fromUrl(
    'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
  )
    /** 这里是配置项 */
  const viewer = new Cesium.Viewer('cesiumContainer', {
    baseLayerPicker: false,
  })
  // 加载ArcGis地图
  viewer.imageryLayers.addImageryProvider(esri)

效果如下:

我们再来看一下之前的地球效果来对比对比:

可以明显看出来ArcGisMapServer提供的地图更加的清晰和立体。

注:加载ArcGis地图服务请使用我上述提供的代码,从Cesium中文网看到的示例代码可能很久没更新了,使用会报错~

当然我们还可以加载一些特定场景的地图,比如夜晚的地球,官网上直接给出了示例代码:

js 复制代码
// addImageryProvider方法用于添加一个新的图层
viewer.imageryLayers.addImageryProvider(await Cesium.IonImageryProvider.fromAssetId(3812))

效果如下:

加载地形

我们回到刚刚的ArcGis地图,我们进入到地球内部查看一些山脉,会发现从俯视角度来看山脉是有轮廓的,但是当我们旋转相机后会发现,实际上地球表面是平的,并没有显示出地形,效果如下:

这时候我们就需要加载出地形数据了

js 复制代码
const esri = await Cesium.ArcGisMapServerImageryProvider.fromUrl(
'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
)
/** 这里是配置项 */
const viewer = new Cesium.Viewer('cesiumContainer', {
    baseLayerPicker: false,
    terrainProvider: await Cesium.CesiumTerrainProvider.fromIonAssetId(1, {
      // 可以增加法线,用于提高光照效果
      requestVertexNormals: true,
      // 可以增加水面特效
      requestWaterMask: true
    })
})
// 加载ArcGis地图
viewer.imageryLayers.addImageryProvider(esri)

效果如下:

可以看到原先的平面通过加载了地形数据,已经有了山势起伏,河流湖泊~

Cesium加载建筑体

我们在实际开发中,比如搭建一个智慧城市,光有地图和地形是远远不够的,还需要加载城市中的建筑模型信息,这时候我们就需要用到Cesium中建筑体的添加和使用的相关功能了,我们以官网的纽约市的模型数据为例:

js 复制代码
  /** 添加建筑物 */
  const tileset = viewer.scene.primitives.add(await Cesium.Cesium3DTileset.fromIonAssetId(75343))
    /** 添加相机信息 */
  const position = Cesium.Cartesian3.fromDegrees(-74.006, 40.7128, 100)
  viewer.camera.setView({
    destination: position,
    orientation: {
      heading: 0,
      pitch: 0,
      roll: 0.0
    }
  })

效果如下:

我们看到纽约市建筑物的数据已经加载出来了,但是看起来都是白白的过于单调,我们还可以通过style来修改建筑物的样式

js 复制代码
tileset.style = new Cesium.Cesium3DTileStyle({
    color: {
      conditions: [
        ['${Height} >= 300', 'rgba(45,0,75,0.5)'],
        ['${Height} >= 100', 'rgb(170,162,204)'],
        ['${Height} >= 50', 'rgb(102,71,151)'],
        ['true', 'rgb(127,59,8)']
      ]
    },
    show: '${Height} > 0',
    meta: {
      description: '"Building id ${id} has height ${Height}."'
    }
  })

现在我们再来看一下效果:

可以看出我们根据建筑物的不同高度,设定了不同的颜色,比如超过300米的建筑就带有透明效果了,比较上图的效果更有层次感。

最后

关于Cesium我也是初窥门径,具体的学习和使用大家还是要以 英文官网 为准,中文网上很多都过时了,使用的时候可能会报错,我已经帮大家踩好坑了😭,也欢迎大家在评论区里多沟通交流,互相学习~

相关推荐
小妖别跑15 分钟前
PDA(程序派生地址,Program Derived Address),为什么有这个地址,而不是直接指定地址
前端·智能合约
2301_7969821431 分钟前
网页打开时,下载的文件text/html/重定向类型有什么作用?
前端·html
重生之我在20年代敲代码33 分钟前
HTML讲解(二)head部分
前端·笔记·html·web app
天下无贼!39 分钟前
2024年最新版TypeScript学习笔记——泛型、接口、枚举、自定义类型等知识点
前端·javascript·vue.js·笔记·学习·typescript·html
小白小白从不日白1 小时前
react 高阶组件
前端·javascript·react.js
Mingyueyixi2 小时前
Flutter Spacer引发的The ParentDataWidget Expanded(flex: 1) 惨案
前端·flutter
Rverdoser3 小时前
unocss 一直热更新打印[vite] hot updated: /__uno.css
前端·css
Bang邦3 小时前
使用nvm管理Node.js多版本
前端·node.js·node多版本管理
podoor3 小时前
wordpress不同网站 调用同一数据表
前端·wordpress
LJ小番茄3 小时前
Vue 常见的几种通信方式(总结)
前端·javascript·vue.js·html