Cesium 上手不完全指北
将最近学习的
CesiumJS做一个系统梳理,从项目配置开始,记录常用API的使用。
环境搭建与安装
首先,什么是 Cesium,Cesium 是一款开源的基于 JavaScript 的 3D 地图框架,即地图可视化框架。产品基于 WebGL 技术,我们可以使用 CesiumJS 创建虚拟场景的 3D 地理信息平台。其目标是用于创建以基于 Web 的地图动态数据可视化。在提升平台的性能、准确率、虚拟化能力、易用性方面提供各种支持。
更多介绍和信息可通过官网进行学习。
注册
Cesium ion 是一个提供瓦片图和 3D 地理空间数据的平台,Cesium ion 支持把数据添加到用户自己的 CesiumJS 应用中。使用二三维贴图和世界地形都需要 ion 的支持,如果没有自己的数据源需要 cesium 提供的数据源就需要申请 ion 的 token,具体可以通过以下链接申请 access token。
在创建 Cesium Viewer 的时候,将 access token 填为自己的 access token 即可。
1 | Cesium.Ion.defaultAccessToken = '<YOUR ACCESS TOKEN HERE>'; |
项目搭建
进入项目搭建过程,项目选择在 Vue 平台上进行实现,首先创建项目安装 cesium 库:
1 | vue create cesium-vue |
注意:目前使用 webpack 进行配置引用最新版本(1.71) cesium 暂时不能导入,实测 `cesium@1.61版本可以进行import` 导入。
项目配置
根目录下新建 vue.config.js 配置文件,对项目进行基本配置:
1 | const CopyWebpackPlugin = require('copy-webpack-plugin') |
在根目录下创建 static 文件夹用于后续 model 和 images 的存放。
组件实现
在 src/components/ 下新建 CesiumViewer.vue 进行组件实现:
1 | <template> |
可以看到地图在调用 Cesium 的 Viewer 时开始构建。Viewer 是 Cesium API 的起点,new Viewer 后便可以看见地球对象。
组件声明
在 App.vue 中引用组件:
1 | <template> |
运行查看效果:
1 | npm run serve |
此时,已经可以看见最开始的地球🌏效果,我们进行一些简单配置和调整:
1 | <script> |
1 | npm run serve |
最终效果如下:
至此,最开始的构建运行就已经完成了,下面对具体 API 进行学习。
Imagery 图层
开始 API 学习之前,为了方便方法实现,使用 ref 在元素上注册一个引用信息,方便通过 ID 直接访问一个子组件实例。
修改如下,引用信息将会注册在父组件的 $refs 对象上,子组件通过 this.$viewer 进行访问。
这里引入图层的概念(Imagery),瓦片图集合根据不同的投影方式映射到虚拟的三维数字地球表面。依赖于相机指向地表的方向和距离,Cesium 会去请求和渲染不同层级的图层详细信息。
详细代码如下:
1 | <template> |
原理上和 PS 的图层一致,多个图层可以添加、移除和排序,渲染并适应到 Cesium 中。
Terrain 地形
Cesium 的地形图层支持渐进式加载和渲染全球高精度地图,并且包括地形地势、水形数据,包括海洋、湖泊、河流、山峰、峡谷等效果。
为了添加地形数据,我们需要创建一个 CesiumTerrainProvider,通过 createWorldTerrain 函数创建一个由 Cesium ion 提供服务的 Cesium WorldTerrian,同时可提供配置项,请求额外的水和光数据,最终我们通过 camera 下的函数定位到创建的位置进行查看:
1 | export default { |
Viewer 控件
回到最开始的调整配置上,我们在 viewerOption 中对 Viewer 声明的一系列基本小控件做了移除和优化操作,具体 API 官方给出了如下描述:
- Geocoder : A location search tool that flies the camera to queried location. Uses Bing Maps data by default.
- HomeButton : Flies the viewer back to a default view.
- SceneModePicker : Switches between 3D, 2D and Columbus View (CV) modes.
- BaseLayerPicker : Chooses the imagery and terrain to display on the globe.
- NavigationHelpButton : Displays the default camera controls.
- Animation : Controls the play speed for view animation.
- CreditsDisplay : Displays data attributions. Almost always required!
- Timeline : Indicates current time and allows users to jump to a specific time using the scrubber.
- FullscreenButton : Makes the Viewer fullscreen.
我们可以根据自身需求选择是否启用。
同时我们还可以对视窗进行配置,到达自己期望的效果,如开启根据动态时间激活太阳位置的光照,对真实地球进行模拟:
1 | export default { |
更近一步,可以利用上一小节使用的 camera 实现主视窗的定位:
1 | // 配置视窗 |
这里需要介绍的是 Scene 的概念,Scence 虚拟场景是所有3D 图形对象和状态的容器,通常不是由开发者直接创建,而是在 Viewer 或者 CesiumWidget 内部隐式创建的。
通过 Scene 场景,我们可以控制 Globe 地球(包括地形和图层)、Camera 相机、Primitives (默认矢量数据层)和 PostProcessStage (后期处理效果)等。
除了以上配置,现在我们需要了解的有以下 Cesium 基本类型的 API:
Cartesian3 : 一个三维笛卡尔坐标——当它被用作相对于地球中心的位置时,使用地球固定框架(
ECEF)。Cartographic : 由经度、纬度(弧度)和
WGS84椭球面高度确定的位置。HeadingPitchRoll : 在东北向上的框架中关于局部轴的旋转(弧度)。航向是围绕负
Z轴的旋转。俯仰是围绕负Y轴的旋转。滚动是关于正X轴的旋转。Quaternion :以
4D坐标表示的3D旋转。
Camera 相机
Camera 是 Cesium 中常用的 API,属于 viewer.scene 中的属性,用来控制当前可见的域。可以控制场景的观察视角,例如旋转、缩放、平移以及飞行定位。
一些最常用的方法如下:
Camera.setView(options): 在特定位置和方向立即设置相机。
Camera.zoomIn(amount): 沿着视角矢量移动摄像机。
Camera.zoomOut(amount): 沿视角矢量向后移动摄像机。
Camera.flyTo(options): 创建从当前相机位置到新位置的动画相机飞行。
Camera.lookAt(target, offset): 定位并定位摄像机以给定偏移量瞄准目标点。
Camera.move(direction, amount): 朝任何方向移动摄像机。
Camera.rotate(axis, angle): 绕任意轴旋转相机。
例子参考上一小节的视窗定位。
Clock 时钟
使用 viewer 的 Clock 和 Timline 可以控制 scene 的时间进度。
下面通过修改 init 函数实现一个日夜交替效果:
1 | export default { |
通过定义 clock,设置起始时间、速率和循环等配置,使用 clockViewModel 在实例中添加时钟视图模型,然后启用光照,实现效果。
注:此效果为演示,init 函数后续恢复为开始的创建实例状态,方便之后的例子使用。
Entity 实体
Cesium 中的所有空间数据都使用 Entity API来表示。Entity API 以一种有效提供灵活的可视化的方式,以便对 Cesium 进行渲染。Cesium Entity 是可以与样式化图形表示配对并定位在空间和时间上的数据对象。
在 Cesium 中,加载点线面矢量有两种方式:
Entity API 是数据驱动的一组高级对象,具有接口一致,容易使用的特点,但性能略低。
Primitive API 是面向三维图形开发,更为底层,具有灵活,性能高的特点,但使用复杂。
其中,Entity API 的使用通过 viewer.entities.add() 方法添加矢量数据:
1 | export default { |
效果如下:
除了绘制实体,还可以通过外部加载的方式进行模型导入。
这里我们在 static 文件夹下放入 J15.glb 文件进行导入:
1 | export default { |