开发中我们通常会需要一个干净的三维地球实例,本文将介绍 Cesium
如何初始化一个地球,包括地图控件的显示隐藏以及一些常用影像和标注的加载
预览Demo
Cesium 是一款面向三维地球和地图的,世界级的 JavaScript
开源产品,它提供了基于 JavaScript
语言的开发包,方便用户快速搭建一款零插件的虚拟地球 Web 应用,并在性能,精度,渲染质量以及多平台,易用性上都有高质量的保证
想了解更多 Cesium 的介绍请看 让GIS三维可视化变得简单-初识Cesium
本文及后续文章启动环境皆是基于 Vue-CLI3.X+
使用我自己写的 CLI
插件 vue-cli-plugin-cesium
零配置搭建 Cesium
环境
具体环境搭建可看 让GIS三维可视化变得简单-Vue项目中集成Cesium
在正式开发之前,我们首先需要去注册一个免费的 Cesium ion
账户
步骤如下
首先,打开 https://cesium.com/ion 然后注册一个新的账户
注册成功后登录,点击 Access Token
,跳转到 「Access Tokens page」 页面
如上所示,选择 「Default」 默认的 access token
拷贝到内容中
Cesium.Ion.defaultAccessToken = ''
当然,如果你只是写写demo,那不写 Token
也行
环境准备就绪之后,我们就可以初始化Cesium实例了,也就是加载地球
如上所示,我们可以使用 new Cesium.CesiumWidget
或者 new Cesium.Viewer
的方式进行初始化,都可以,给一个容器挂载即可,运行项目后效果如下
可能细心的小伙伴注意到了我们初始化的 viewer
实例并没有写在 data
里,这是因为Vue中会为 data
中的属性做数据劫持,如果属性是一个对象,将会递归进行数据劫持,viewer
这个实例中的属性数量非常多,如果将它放置 data
中。。。只有一个下场,浏览器崩溃
我们可以在组件上放直接声明一个 viewer
变量,也可以使用 window.viewer
把 viewer
挂载到 window
上面,都可以避免这个问题
在 Vue + Cesium
开发中和实例有关的数据都不要放在data中,这点一定需要注意
上面我们可以看到,在默认初始化里,页面上有很多控件,开发时我们基本用不到,但是还是先来介绍下这些控件的作用
在创建 Cesium
实例时,new Cesium.Viewer
构造函数有两个参数
实例挂载的元素 必选项
options 初始化配置对象 可选项
在 options
对象中,我们可以配置初始化的一些控件显示隐藏以及一些渲染配置,这里列举出一些常用的配置
viewer = new Cesium.Viewer("cesiumContainer", {
animation: false, // 隐藏动画控件
baseLayerPicker: false, // 隐藏图层选择控件
fullscreenButton: false, // 隐藏全屏按钮
vrButton: false, // 隐藏VR按钮,默认false
geocoder: false, // 隐藏地名查找控件
homeButton: false, // 隐藏Home按钮
infoBox: false, // 隐藏点击要素之后显示的信息窗口
sceneModePicker: false, // 隐藏场景模式选择控件
selectionIndicator: true, // 显示实体对象选择框,默认true
timeline: false, // 隐藏时间线控件
navigationHelpButton: false, // 隐藏帮助按钮
scene3DOnly: true, // 每个几何实例将只在3D中呈现,以节省GPU内存
shouldAnimate: true, // 开启动画自动播放
sceneMode: 3, // 初始场景模式 1:2D 2:2D循环 3:3D,默认3
requestRenderMode: true, // 减少Cesium渲染新帧总时间并减少Cesium在应用程序中总体CPU使用率
// 如场景中的元素没有随仿真时间变化,请考虑将设置maximumRenderTimeChange为较高的值,例如Infinity
maximumRenderTimeChange: Infinity
})
我们使用上面 options
配置,即可把页面上的控件全部隐藏掉,如下图所示
可以看到,虽然控件已经没有了,但是屏幕下方还有 Cesium
的 logo
信息,我们需要让它也不显示
// 隐藏下方Cesium logo
viewer.cesiumWidget.creditContainer.style.display = "none"
如上所示,只需再来一行额外的配置隐藏 logo
信息,即可获得一个干净的地球实例,最终效果图如下
Cesium
支持多种服务来源的高精度影像(地图)数据的加载和渲染,图层支持排序和透明混合,每个图层的亮度(brightness),对比度( contrast),灰度(gamma),色调(hue),饱和度(saturation)都是可以动态修改的
这里我们忽略细节,先简单介绍下影像相关的几个类,然后直接写代码去添加一些不同的常用影像图层
「PS:Cesium是一个构造函数,在这个构造函数上又有无数个静态属性,它们也是不同作用的构造函数,按照OOP的方式理解,Cesium是一个父类,而它又有很多子类用来做不同的事情」
Cesium.ImageryProvider类
说到影像这块儿,首先,我们要了解一下 imageryProvider
这个类,Imagery
可以翻译为图像、影像,这里就统一称之为影像
ImageryProvider
类及其子类封装了加载各种影像图层的方法,其中 Cesium.ImageryProvider
类是抽象类、基类或者可将其理解为接口,它不能被直接实例化
可以将 ImageryProvider
看作是影像图层的数据源,我们想使用哪种影像图层数据或服务就用对应的 ImageryProvider
类型去加载即可
ImageryProvider
类包含的类型
ArcGisMapServerImageryProvider
ArcGIS Online和Server的相关服务
BinaMapsImageryProvider
Bing地图影像,可以指定mapStyle,详见BingMapsStyle类
GoogleEarthEnterpriselmageryProvider
企业级服务
GridImageryProvider
渲染每一个瓦片内部的格网,了解每个瓦片的精细度
IonImageryProvider
Cesium ion REST API提供的影像服务
MapboxImageryProvider
Mapbox影像服务,根据 mapId 指定地图风格
MapboxStyleImageryProvider
Mapbox影像服务,根据 styleId 指定地图风格
createOpenStreetMapImageryProvider
OpenStreetMap提供的影像服务
SingleTilelmageryProvider
单张图片的影像服务,适合离线数据或对影像数据要求并不高的场景下
TileCoordinatesImageryProvider
渲染每一个瓦片的围,方便调试
TileMapServicelmageryProvider
根据MapTiler规范,可自己下载瓦片,发布服务,类似ArcGIS影像服务的过程
UrlTemplateImageryProvider
指定url的format模版,方便用户实现自己的Provider,比如国内的高德,腾讯等影像服务,url都是一个固定的规范,都可以通过该Provider轻松实现。而OSM也是通过该类实现的
WebMapServiceImageryProvider
符合WMS规范的影像服务都可以通过该类封装,指定具体参数实现
WebMapTileServicelmageryProvider
服务WMTS1.0.0规范的影像服务,都可以通过该类实现,比如国内的天地图
Cesium.ImageryLayer类
要知道,一份 GIS
数据会被组织成图层符号化并渲染,数据相当于内在血液、内脏,信息量丰富,而图层相当于外在皮毛、衣服,用于呈现给外界
Cesium
同样将数据源组织成图层符号化并渲染,Cesium.ImageryLayer
类就用于表示 Cesium
中的影像图层,它就相当于皮毛、衣服,将数据源包裹,它需要数据源为其提供内在丰富的地理空间信息和属性信息
Cesium.ImageryLayerCollection类
Cesium.ImageryLayerCollection
类是 ImageryLayer
实例的容器,它可以装载、放置多个 ImageryLayer
实例,而且它内部放置的 ImageryLayer
实例是有序的
Cesium.Viewer
类对象中包含的 imageryLayers
属性就是 ImageryLayerCollection
类的实例,它包含了当前 Cesium
应用程序所有的 ImageryLayer
类对象,即当前地球上加载的所有影像图层
知道了影像图层基础的体系结构,那么影像加载就简单了,上面我们也可以看到 ImageryProvider
类种类非常多,列举出来是为了给大家展示下它可以加载什么影像,但是一一演示不现实,所以接下来我们就来看几个常见影像加载
加载天地图影像
按照上述所说,首先我们要加载影像图层的数据源,Cesium地球默认加载的是 bing
地图影像,所以我们要先从容器中删除这个默认影像
viewer.imageryLayers.remove(viewer.imageryLayers.get(0))
然后,我们加载影像图层的数据源
let tianditu = new Cesium.WebMapTileServiceImageryProvider({
url:"http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=ebf64362215c081f8317203220f133eb",
layer: "tdtBasicLayer",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "GoogleMapsCompatible",
show: false,
})
url
字段中的 tk
为天地图服务token,去天地图官网注册申请一个即可
随后,我们将数据源添加至 ImageryLayer
类容器进行符号化并渲染即可
将数据源添加至 ImageryLayer
类容器进行符号化并渲染有两种方法,第一种是在初始化 viewer
实例时的 options
配置中,你可以直接在 options
对象的 imageryProvider
属性中放置数据源即可
new Cesium.Viewer("cesiumContainer",{
imageryProvider: tianditu
})
第二种方法,使用 viewer
实例中 imageryLayers
属性的 addImageryProvider
方法来添加即可
let imagery = viewer.imageryLayers.addImageryProvider(tianditu)
天地图影像预览如下
加载谷歌影像
上面步骤已经知悉,我们就不一一叙说了,下面直接看代码就好
viewer.imageryLayers.remove(viewer.imageryLayers.get(0))
let imagery = viewer.imageryLayers.addImageryProvider(
new Cesium.UrlTemplateImageryProvider({
url: "http://mt1.google.cn/vt/lyrs=s&hl=zh-CN&x={x}&y={y}&z={z}&s=Gali",
baseLayerPicker : false
})
)
谷歌影像预览如下
加载ArcGIS影像
viewer.imageryLayers.remove(viewer.imageryLayers.get(0))
let imagery = viewer.imageryLayers.addImageryProvider(
new Cesium.ArcGisMapServerImageryProvider({
url:'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer',
baseLayerPicker : false
})
)
ArcGIS影像预览如下
加载高德影像
viewer.imageryLayers.remove(viewer.imageryLayers.get(0))
let imagery = viewer.imageryLayers.addImageryProvider(
new Cesium.UrlTemplateImageryProvider({
maximumLevel:18,//最大缩放级别
url : 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
style: "default",
format: "image/png",
tileMatrixSetID: "GoogleMapsCompatible"
})
)
高德影像预览如下
加载天地图标注
上述影像的加载,可以看到,地图上是没有标注的,我们需要额外加载标柱,同样的,它也是图层
let label = viewer.imageryLayers.addImageryProvider(
new Cesium.WebMapTileServiceImageryProvider({
url: "http://t0.tianditu.com/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default.jpg"+"&tk="+"19b72f6cde5c8b49cf21ea2bb4c5b21e",
layer: "tdtAnnoLayer",
style: "default",
maximumLevel: 18, //天地图的最大缩放级别
format: "image/jpeg",
tileMatrixSetID: "GoogleMapsCompatible",
show: false,
})
)
同样的,和天地图影像一样,不要忘了替换 tk
哦
天地图标注预览如下
影像亮度调整
我们加载影像拿到影像实例 imagery
后,可以通过其 brightness
属性调节亮度,取值 0~1
,默认为1
imagery.brightness = 0.9
这次就到这了,其实不止是做Cesium开发的人群,做前端的同学学一学这些还是有些用处的,可以为你的页面或项目增色不少,后续内容请参考暂定目录
让GIS三维可视化变得简单-初识Cesium
让GIS三维可视化变得简单-Vue项目中集成Cesium
让GIS三维可视化变得简单-Cesium地球初始化
暂定 - 让GIS三维可视化变得简单-Cesium坐标转换
暂定 - 让GIS三维可视化变得简单-Cesium球体自转
暂定 - 让GIS三维可视化变得简单-Cesium实体Entity及事件
暂定 - 让GIS三维可视化变得简单-Cesium模型数据之3DTiles
暂定 - 让GIS三维可视化变得简单-Cesium模型数据之gltf
暂定 - 让GIS三维可视化变得简单-Cesium模型数据之geojson
暂定 - 让GIS三维可视化变得简单-Cesium模型数据之czml
暂定 - 让GIS三维可视化变得简单-Cesium流动线绘制
暂定让GIS三维可视化变得简单-Cesium气泡弹窗
暂定 - 让GIS三维可视化变得简单-Cesium粒子系统(火灾、雪花、喷水)
暂定 - 让GIS三维可视化变得简单-Cesium鹰眼图
暂定 - 让GIS三维可视化变得简单-Cesium结合Echarts
Cesium国内教程很少,文档也是英文的,不太好入手,所以此系列只是简单入门以及一些效果制作(说白了就是介绍一些简单使用和一些好玩的例子),每一篇介绍一个点,挺难涉及到Cesium核心原理,因为我也在学习中,看后期个人学习情况,我是觉得什么好玩就想学。。。
没有专业的 GIS 基础知识积累真的好难,此系列不定期更新,暂时先排这么多,不定期插入,不定期更新,敬请期待
原创不易,看完望点赞、在看、关注、转发,此文收录在 GitHub,更多精彩请看 isboyjc/blog/issues
如有错误请指出,互相学习,先行谢过,一个前端的 Cesium
学习过程的积累分享,自知深度不够,不喜勿喷
是前端,又不只是前端,欢迎关注「不正经的前端」,认真分享干货