Vue2项目中集成Cesium(VueCLi 3.0+)

345 阅读3分钟

1. Cesium介绍

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

  • 支持全球级别的高精度的地形和影像服务
  • 支持 2D、2.5D、3D 形式的地图展示,真正的二三维一体化
  • 支持矢量、海量模型数据(倾斜,BIM,点云等)
  • 支持基于时间轴的动态数据可视化展示

image.png

使用 Cesium, 浏览器必须支持 WebGL。目前,大多数平台和浏览器都支持WebGL,运行 Cesium 并没有太大的问题,但效果和性能是否能够满足不同的需求,就需要考虑很多细节和额外因素

2 html中引入Cesium

2.1 官网下载Cesium

Downloads – Cesium 官网下载Cesium 包即可,Cesium 每个月都会更新一个版本

下载下来解压后有很多文件,如下图

image.png

包括 Cesium API 源代码 Source 文件夹,以及编译后的 Build 文件夹,还有Demo、API文档、沙盒等等,这些都不用管

我们只需要 Build 文件夹下面的 Cesium 这个文件夹,它是编译后 Cesium 包的正式版本

image.png

2.2 html中引入Cesium的示例

image.png

image.png

image.png

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <!-- 第一步 引入cesium.js,该文件定义了 Cesium 对象,它包含了我们需要的一切 -->
    <script src="./Cesium/Cesium.js"></script>
    <style>
      /* 第二步 引入 widgets.css,为了能使用Cesium 各个可视化控件 */
      @import url(./Cesium/Widgets/widgets.css);
      html,
      body,
      #cesiumContainer {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <!-- 第三步 创建一个 div,用来作为三维地球的容器 -->
    <div id="cesiumContainer"></div>
    <script>
      console.log(Cesium);
      // 第四步 在 JS 中初始化 CesiumViewer 实例
      window.onload = function () {
        let viewer = new Cesium.Viewer('cesiumContainer')
      }
    </script>
  </body>
</html>

装一个 live-server 运行

3. Vue引入Cesium

3.1 将cesium放在public目录下

image.png

3.2 在index.html中引入cesium

image.png

3.3 申请Token

  • 打开 cesium.com/ion/,注册一个免费的 Cesium ion 账户
  • 注册成功后登录,点击 Access Token,跳转到 Access Tokens page 页面

image.png

3.4 简单初始化地球,隐藏控件

<template>
  <div id="cesiumContainer"></div>
</template>

<script>
export default {
  data() {
    return {}
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
      Cesium.Ion.defaultAccessToken =
        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlODMwYTEzNC1jMjZmLTRmMmYtOWY5MC0wNDU1NGMyN2FlNjEiLCJpZCI6MTUwMTMxLCJpYXQiOjE2ODgwMDc5MDN9.sxiJUx3KmcotP_57RZchyKUO165fswyfM7-xB9BiiZI'

      var 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
      })
      console.log('viewer', viewer)
      // 隐藏下方Cesium logo
      viewer.cesiumWidget.creditContainer.style.display = 'none'
    }
  }
}
</script>
<style lang="scss" scoped>
#cesiumContainer {
  width: 100%;
  height: 100%;
}
</style>

image.png

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

4. Cesium 加载影像

Cesium 支持多种服务来源的高精度影像(地图)数据的加载和渲染,图层支持排序和透明混合,每个图层的亮度(brightness),对比度( contrast),灰度(gamma),色调(hue),饱和度(saturation)都是可以动态修改的

PS:Cesium是一个构造函数,在这个构造函数上又有无数个静态属性,它们也是不同作用的构造函数,按照面向对象(OOP)的方式理解,Cesium是一个父类,而它又有很多子类用来做不同的事情

4.1 Cesium.ImageryProvider类

imageryProvider 类,Imagery 可以翻译为图像、影像

  • ImageryProvider 类及其子类封装了加载各种影像图层的方法
  • 其中Cesium.ImageryProvider 类是抽象类、基类或者可将其理解为接口,它不能被直接实例化
  • 可以将 ImageryProvider 看作是影像图层的数据源,我们想使用哪种影像图层数据或服务就用对应的 ImageryProvider 类型去加载即可

4.2 Cesium.ImageryLayer类

  • Cesium 将数据源组织成图层符号化并渲染
  • Cesium.ImageryLayer 类就用于表示 Cesium 中的影像图层,它就相当于皮毛、衣服,将数据源包裹,它需要数据源为其提供内在丰富的地理空间信息和属性信息

4.3 Cesium.ImageryLayerCollection类

  • Cesium.ImageryLayerCollection 类是 ImageryLayer 实例的容器,它可以装载、放置多个 ImageryLayer 实例,而且它内部放置的 ImageryLayer 实例是有序的
  • Cesium.Viewer 类对象中包含的 imageryLayers 属性就是 ImageryLayerCollection 类的实例,它包含了当前 Cesium 应用程序所有的 ImageryLayer 类对象,即当前地球上加载的所有影像图层

4.4 示例——加载ArcGIS影像

image.png

<template>
  <div id="cesiumContainer"></div>
</template>

<script>
export default {
  data() {
    return {}
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
      Cesium.Ion.defaultAccessToken =
        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlODMwYTEzNC1jMjZmLTRmMmYtOWY5MC0wNDU1NGMyN2FlNjEiLCJpZCI6MTUwMTMxLCJpYXQiOjE2ODgwMDc5MDN9.sxiJUx3KmcotP_57RZchyKUO165fswyfM7-xB9BiiZI'

      var 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
      })
      console.log('viewer', viewer)
      // 隐藏下方Cesium logo
      viewer.cesiumWidget.creditContainer.style.display = 'none'
      // 首先要加载影像图层的数据源,Cesium地球默认加载的是 bing 地图影像,所以要先从容器中删除这个默认影像
      viewer.imageryLayers.remove(viewer.imageryLayers.get(0))
      // 加载ArcGIS影像
      let imagery = viewer.imageryLayers.addImageryProvider(
        new Cesium.ArcGisMapServerImageryProvider({
          url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer',
          baseLayerPicker: false
        })
      )
      console.log('imagery', imagery)
      // 影像亮度调整
      imagery.brightness = 0.3
    }
  }
}
</script>
<style lang="scss" scoped>
#cesiumContainer {
  width: 100%;
  height: 100%;
}
</style>

5. 相关资源网站