前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >让GIS三维可视化变得简单-Cesium地球初始化

让GIS三维可视化变得简单-Cesium地球初始化

作者头像
isboyjc
发布2022-03-28 18:11:40
1.9K0
发布2022-03-28 18:11:40
举报
文章被收录于专栏:不正经的前端不正经的前端

前言

开发中我们通常会需要一个干净的三维地球实例,本文将介绍 Cesium 如何初始化一个地球,包括地图控件的显示隐藏以及一些常用影像和标注的加载

预览Demo[1]

Cesium 是一款面向三维地球和地图的,世界级的 JavaScript 开源产品,它提供了基于 JavaScript 语言的开发包,方便用户快速搭建一款零插件的虚拟地球 Web 应用,并在性能,精度,渲染质量以及多平台,易用性上都有高质量的保证

想了解更多 Cesium 的介绍请看 👉 让GIS三维可视化变得简单-初识Cesium

环境搭建

本文及后续文章启动环境皆是基于 Vue-CLI3.X+

使用我自己写的 CLI 插件 vue-cli-plugin-cesium 零配置搭建 Cesium 环境

具体环境搭建可看 👉 让GIS三维可视化变得简单-Vue项目中集成Cesium

地球初始化

申请Token

在正式开发之前,我们首先需要去注册一个免费的 Cesium ion 账户

步骤如下

首先,打开 https://cesium.com/ion[2] 然后注册一个新的账户

注册成功后登录,点击 Access Token,跳转到 「Access Tokens page」 页面

如上所示,选择 「Default」 默认的 access token 拷贝到内容中

代码语言:javascript
复制
Cesium.Ion.defaultAccessToken = '<YOUR ACCESS TOKEN HERE>'

当然,如果你只是写写demo,那不写 Token 也行

默认初始化

环境准备就绪之后,我们就可以初始化Cesium实例了,也就是加载地球

代码语言:javascript
复制
<template>
  <div class="map-box">
    <div id="cesiumContainer"></div>
  </div>
</template>

<script>
var viewer = null
export default {
  name: "No01Init",
  data() {
    return {}
  },
  mounted() {
    Cesium.Ion.defaultAccessToken = '<YOUR ACCESS TOKEN HERE>'
    // viewer = new Cesium.CesiumWidget('cesiumContainer')
    viewer = new Cesium.Viewer("cesiumContainer")

    console.log(viewer)
  },
}
</script>

<style scoped>
.map-box {
  width: 100%;
  height: 100%;
}
#cesiumContainer {
  width: 100%;
  height: 100%;
}
</style>

如上所示,我们可以使用 new Cesium.CesiumWidget 或者 new Cesium.Viewer 的方式进行初始化,都可以,给一个容器挂载即可,运行项目后效果如下

可能细心的小伙伴注意到了我们初始化的 viewer 实例并没有写在 data 里,这是因为Vue中会为 data 中的属性做数据劫持,如果属性是一个对象,将会递归进行数据劫持,viewer 这个实例中的属性数量非常多,如果将它放置 data 中。。。只有一个下场,浏览器崩溃

我们可以在组件上放直接声明一个 viewer 变量,也可以使用 window.viewerviewer 挂载到 window 上面,都可以避免这个问题

Vue + Cesium 开发中和实例有关的数据都不要放在data中,这点一定需要注意

控件隐藏

上面我们可以看到,在默认初始化里,页面上有很多控件,开发时我们基本用不到,但是还是先来介绍下这些控件的作用

在创建 Cesium 实例时,new Cesium.Viewer 构造函数有两个参数

  • 实例挂载的元素 必选项
  • options 初始化配置对象 可选项

options 对象中,我们可以配置初始化的一些控件显示隐藏以及一些渲染配置,这里列举出一些常用的配置

代码语言:javascript
复制
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 配置,即可把页面上的控件全部隐藏掉,如下图所示

可以看到,虽然控件已经没有了,但是屏幕下方还有 Cesiumlogo 信息,我们需要让它也不显示

代码语言:javascript
复制
// 隐藏下方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 地图影像,所以我们要先从容器中删除这个默认影像

代码语言:javascript
复制
viewer.imageryLayers.remove(viewer.imageryLayers.get(0))

然后,我们加载影像图层的数据源

代码语言:javascript
复制
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 属性中放置数据源即可

代码语言:javascript
复制
new Cesium.Viewer("cesiumContainer",{
  imageryProvider: tianditu
})

第二种方法,使用 viewer 实例中 imageryLayers 属性的 addImageryProvider 方法来添加即可

代码语言:javascript
复制
let imagery = viewer.imageryLayers.addImageryProvider(tianditu)

天地图影像预览如下

加载谷歌影像

上面步骤已经知悉,我们就不一一叙说了,下面直接看代码就好

代码语言:javascript
复制
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影像
代码语言:javascript
复制
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影像预览如下

加载高德影像
代码语言:javascript
复制
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"
  })
)

高德影像预览如下

加载天地图标注

上述影像的加载,可以看到,地图上是没有标注的,我们需要额外加载标柱,同样的,它也是图层

代码语言:javascript
复制
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

代码语言:javascript
复制
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[3]

如有错误请指出,互相学习,先行谢过,一个前端的 Cesium 学习过程的积累分享,自知深度不够,不喜勿喷

Reference

[1]预览Demo: https://isboyjc.top/cesiumdemo/cesium-init/index.html

[2]https://cesium.com/ion: https://cesium.com/ion/

[3]isboyjc/blog/issues: https://github.com/isboyjc/blog/issues

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 不正经的前端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 环境搭建
  • 地球初始化
    • 申请Token
      • 默认初始化
        • 控件隐藏
          • 加载影像
            • Cesium.ImageryProvider类
            • Cesium.ImageryLayer类
            • Cesium.ImageryLayerCollection类
            • 加载天地图影像
            • 加载谷歌影像
            • 加载ArcGIS影像
            • 加载高德影像
            • 加载天地图标注
            • 影像亮度调整
        • 后续
        • 结束
          • Reference
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档