项目背景
因为工作的需要,现在需要在项目中进行3d可视化的开发,目前我选择的技术选型是Cesium+SuperMap的技术组合。
技术调研
Cesium
Cesium是目前世界上比较流行跨浏览器展示三维地球和地图的JavaScript库。Cesium使用WebGL进行硬件加速图形,使用时不需要任何插件支持。
SuperMap
3d可视化项目起步
引入包
随着前端工程化的概念的流行,Cesium已经在npm上上传了依赖。
我们使用npm 命令去引入先关的依赖
npm i cesium --save
和所有的3d可视化项目一样,Cesium都需要一个实例,作为gis的入口
import {Viewer} from "cesium"
const domId = "container" // 将gis渲染到id=container的dom元素上
const option = {
electionIndicator: false, // 是否显示选中地图元素标识控件
animation: false, // 是否显示动画控件
baseLayerPicker: false, // 是否显示图层选择控件
geocoder: false, // 是否显示地名查找控件
timeline: false, // 是否显示时间线控件
sceneModePicker: false, // 是否显示投影方式控件
navigationHelpButton: false, // 是否显示帮助信息控件
infoBox: false, // 是否显示点击要素之后显示的信息
homeButton: false, // 是否显示主页控件
fullscreenButton: false // 是否显示全屏控件
}
const viewer = new Viewer(domId,option)
this.viewer = viewer
ps:项目在开发过程中,一般不需要使用Cesium的原生控件ui,这里我们做一些隐藏
cesium的实例自带版权信息,这里也一并隐藏了
const { cesiumWidget } = this.viewer
viewer.cesiumWidget.creditContainer.style.display = "none";
这里最终的效果如下
Cesium需要token,我们这里只是使用了官方默认且自带的token,在此后的更新中我再教大家如何申请token,这里仅仅展示功能,用默认的token就可以了。
图层
仅仅是有一个earth是不够的,我们需要在earth上展示国家,城市,线路和建筑等,这些也是地图的常见元素,所以我们需要图层来显示这些元素。
何为图层?
简单来说,就是地理图上的底图,它是一切地图元素(国家,城市,建筑,站点等)的承载
如果你手机里有百度地图,高德地图或者苹果地图,那么理解起来会非常简单
如上,是我使用百度地图随意截图的画面,这里展示的就是一张地图,上面展示了写字楼,广场,学院等元素都在上面。
图层也分很多种,这里只是其中的一种,其他的还有比如显示水纹的水纹图,显示国界线的国家图等等,根据项目需要,我们可以自由引入。
元素
图层只是Cesium的最底层,现在底层有了,我们就需要在上面放置我们的元素
在几何学的入门知识中,2个点构成1条线,多条线构成1个平面,因而,在Cesium中,点,线和面就构成了基本的元素
如上图所示,虎门站和市公园分别是一个点元素,公园和虎门站的连线就构成了线元素。
坐标系
元素要放置在图层的某个位置,就需要我们找到这个元素的精准位置,既然要锁定位置,那就需要坐标系。
Cesium目前采用的是WGS84坐标和笛卡尔空间坐标2种坐标系。
WGS84坐标系
该坐标系,以地球球心为原地,地心空间直角坐标系的Z轴指向BIH (国际时间服务机构)1984.0定义的协议地球极(CTP)方向,X轴指向BIH 1984.0的零子午面和CTP赤道的交点,Y轴与Z轴、X轴垂直构成右手坐标系。它是目前全世界使用率最高的坐标系,google地图和电子指南针等,都是使用的这个坐标系。
Cesium提供了相关的API,来进行WSG84坐标的描述,这个API就是Cartographic类,Cartographic类可以通过地理坐标系的经纬度的弧度来实现WSG84经纬度坐标弧度制。
import {Cartographic} from "cesium";
const cartographic = new Cartographic(longitude,latitude,height)
其中,longitude是经度,latitude是纬度,height是高度且单位是米
由于Cesium没有具体的经纬度对象,所以我们需要利用弧度来先转换成经纬度。
举个例子吧,我们在Cesium里面表示北京市的经纬度
import {
Cartographic
} from "cesium";
// 北京市的经纬度是北纬39.9",东经116. 3
const longitude = 116.3;
const latitude = 39.9;
/**
* 这里的height其实就是地球的半径,我们直接在实例中去获取地球的椭圆对象即可, 我印象中是6378137
* 因为地球是一个椭圆,所以我们采用maximumRadius获取椭圆的最大半径
*/
const height = this.viewer.scene.globe.ellipsoid.maximumRadius
const cartographic = new Cartographic.fromDegrees(longitude,latitude,height)
笛卡尔空间坐标系
Cesium同时也使用了笛卡尔空间坐标系,这个坐标系可就简单了,是高中立体几何知识。
所以这里我们就不展开细说了。
还是同样的例子,以北京市为例,且看下面的例子
import { Cartesian3 } from "cesium";
cost longitude = 116.3;
const latitude = 39.9;
const height = this.viewer.scene.globe.ellipsoid.maximumRadius;
const cartographic = new Cartesian3.fromDegrees(longitude,latitude,height)
Camera
我们在viewer实例中,之所以可以看到一个个entity,是因为camera的存在。所以这里我们有必要对Camera对象有个初步的了解。
在我们初始化Cesium的时候,我们本身就初始化了Camera对象,可在viewer实例中看见
const camera = this.viewer.camera;
在项目中,我们不会直接给用户看整个地球,我们需要的是lookAt某个具体的位置。
还是回到场景中,我们假设实例化之后,camera要lookAt北京市