写在前面:随着市场对数字孪生的需求日益增多,对于前端从业者的能力从对框架vue、react的要求,逐步扩展到2D、3D空间的交互,为用户提供更紧密的立体交互。近年来前端对GIS的需求日益增多。本文将记录WebGIS的学习之旅,从实战项目入门,挖掘Cesium.js API,并逐步丰富项目。
目录
一、WebGIS简介
WebGIS(Web地理信息系统)是指利用 Web 技术来构建和展示地理信息系统(GIS),使用户可以通过 Web 浏览器访问、查询、分析和可视化地理空间数据。WebGIS 通常结合地图服务、地理信息数据库、前端地图库和相关的数据处理技术,为用户提供交互式的地图浏览和空间数据分析功能。
CesiumJS简介
Cesium是使用JavaScript开发的基于WebGL的,实现三维地球和地图可视化的JS库。支持海量的三维模型数据、影像数据,地形数据,矢量数据等丰富的地理数据加载。在智慧城市、交通、规划、城市管理、地形仿真领域有着非常广泛的应用。Cesium为三维的GIS提供了一个高效的数据可视化平台。
CesiumJS是目前最流行的三维数字地球渲染引擎,不仅可以在网页端高效运行,而且可以借助虚幻引擎在CS端渲染出和游戏一样的高质量效果。
Cesium支持3D、2D、2.5D形式的地图展示,可以自行绘制图形,高亮区域。
CesiumJS源代码
访问官网
二、项目快速搭建
快速搭建一个下面的Cesium.js官方示例
使用vite快速搭建vue3+typeScript
使用下面命令创建vue项目
npm create vite@latest
- 设置项目名称
- 选择使用vue
- 选择是否使用typescript+vue
安装Cesium插件
npm i cesium vite-plugin-cesium vite -D
配置vite.config.js
vite.config.js中配置如下:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import cesium from 'vite-plugin-cesium';
export default defineConfig({
plugins: [vue(),cesium()]
});
清空style.css
在App.vue里面进行全局导入
需要id为cesiumContainer的div挂载后再执行Cesium的代码,给html、body加样式屏幕撑满。
注意:viewer实例的创建必须在onMounted之后进行,确保元素已经挂载到页面上,保证地图的顺利渲染
<template>
<div id="cesiumContainer"></div>
</template>
<script setup>
import * as Cesium from 'cesium';
import { onMounted } from 'vue';
onMounted(() => {
const viewer = new Cesium.Viewer('cesiumContainer',{
infoBox: false, // 禁用沙箱,解决控制台报错
});
});
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
html,body,#cesiumContainer{
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
</style>
这段代码中的cesiumContainer是用作Cesium Viewer(查看器)的挂载点。在WebGL渲染中,无论是二维还是三维图像,都需要一个容器来承载渲染的内容。在这里,<div id="cesiumContainer"></div> 元素就是用来承载Cesium Viewer所渲染的内容。
当你创建一个Cesium Viewer实例时,你需要指定一个DOM元素作为其容器,Cesium会将渲染的内容放置在这个DOM元素中。
通过new Cesium.Viewer('cesiumContainer', {...}),将Cesium Viewer挂载到id为cesiumContainer的div元素上,从而实现了Cesium渲染的效果。
其实无论是二维还是三维图像渲染,都需要一个挂载点来显示渲染的内容,而在这里cesiumContainer就充当了这样的作用。原理都是相同的哈~
运行程序
npm run dev
即可得到上面示例的gif效果
页面涉及的空间如下,所有的空间都可以关闭
geocoder: 位置查找工具
baseLayerPicker: 图层选择器(地形影像服务)
homeButton: 视角返回初始位置
fullscreenButton: 全屏
animation: 左下角仪表盘(动画器件)timeline: 底部时间线
sceneModePicker: 选择视角的模式(球体、平铺、斜视平铺)
navigationHelpButton: 导航帮助按钮
infoBox: 信息框控件
navigationInstructionsInitiallyVisible: 导航说明初始可见
shouldAnimate: 动画
requestWaterMask: 请求水面罩
requestVertexNormals: 请求顶点法线
三、认识Cesium四大类
查看器类Viewer
Viewer是三维数据展示的主要窗口,此外还包含了一些基础控件。在定义Viewer对象的同时需要设定基础部件、图层等的初始化状态。
用法示例:
接收两个参数,第一个参数指定地图主窗口div的id;第二个参数options是Viewer的可选设置参数。包含图层、地形、时间系统等参数;种类多样。
const viewer = new Cesium.Viewer('cesiumContainer',{
infoBox: false,
});
第二个参数接收的对象表示页面可关闭的控件,控件参数解释见上,代码示例
Viewer类,关闭左下角仪表盘及底部时间线
<script setup lang="ts">
import * as Cesium from 'cesium';
import { onMounted,ref} from 'vue';
const viewer = ref();
onMounted(() => {
viewer.value = new Cesium.Viewer('cesiumContainer', {
infoBox: false, // 禁用沙箱,解决控制台报错
animation: false,//关闭左下角仪表盘(动画器件)
timeline:false,//底部时间线
});
});
效果展示:红色圈出的部分是隐藏的控件
场景类Scene
在Cesium中Scene是非常重要的类,是所有3D图像对象的容器,是在Viewer内部隐式创建的。用于基础地理环境设置
代码示例:隐藏地球
<script setup lang="ts">
import * as Cesium from 'cesium';
import { onMounted,ref} from 'vue';
const viewer = ref();
onMounted(() => {
viewer.value = new Cesium.Viewer('cesiumContainer', {
infoBox: false, // 禁用沙箱,解决控制台报错
animation: false,//关闭左下角仪表盘(动画器件)
timeline:false,//底部时间线
});
viewer.value.scene.globe.show = false;
});
scene可以对场景进行交互:如鼠标事件、相机事件;可以通过scene控制相机对视口进行切换;
代码示例:
viewer.value.scene.camera.setView({
destination:Cesium.Cartesian3.fromDegrees(116.39,39.9,1500)
})
此外scene还可以修改地球的图层 样式或地形数据,更可以在图层上绘制几何体,点、线、面
实体类
Entity
Entity是由Primitive封装而来,Entity并不属于Scene。
相比较而言,Entity封装程度高,构造简单,使用便捷,使得开发者专注于数据的呈现,而不必担心底层的可视化机制。它还提供了用于构建复杂的、时间动态可视化的结构。
Entity在使用中主要用于加载实体模型,几何图形;对其进行样式设置,动效修改等
代码示例:
增加一个尺寸为100像素的绿色圆点,先设置当前圆点的位置。fromDegrees内的三个参数分别是经度、维度和高度;给圆点设置大小,pixelSize,在设置颜色;将摄像头设置在圆点处,使得我们可以观测到。
<script setup lang="ts">
import * as Cesium from 'cesium';
import { onMounted,ref} from 'vue';
const viewer = ref();
onMounted(() => {
viewer.value = new Cesium.Viewer('cesiumContainer', {
infoBox: false, // 禁用沙箱,解决控制台报错
animation: false,//关闭左下角仪表盘(动画器件)
timeline:false,//底部时间线
});
const entity = viewer.value.entities.add({
position: Cesium.Cartesian3.fromDegrees(116.39, 39.91, 400),
point: {
pixelSize: 100,
color: new Cesium.Color(0,1,0,1)
}
})
viewer.value.trackedEntity = entity;
});
</script>
效果展示
数据源集合类DataSourceCollection
在GIS开发中加载矢量数据是必不可少的功能。在Cesium加载以下几种格式的数据可实现矢量数据的加载和存取。
DataSourceCollection是Cesium中加载矢量数据的主要方式之一;最大特点是支持加载矢量数据集合外部文件的调用。主要有三种调用方法:
CzmlDataSource 加载czml格式
KmlDataSource 加载kml格式
GeoJsonDataSource 加载GeoJSON格式
缺少数据源,暂时用代码表示
viewer.value.dataSource.add(
Cesium.GeoJsonDataSource.load("../../**.topojson")
)
四、Cesium的坐标与转换
Cesium是具有真实地理坐标的三维球体,而用户是通过二维屏幕与Cesium进行操作。我们将三维模型绘制在三维球体上就需要地理坐标和屏幕坐标之间做转换。接下来介绍Cesium的五种坐标系,及坐标系直接的相互转换
1.WGS84经纬度坐标系-没有实际的对象
简单点就是下面介绍的,WGS84是一种坐标系统,用于GPS全球定位系统使用。快把你初中高中的地理知识拿出来回忆回忆