分享vue3+OpenTiny UI+cesium.js实现三维地球

效果图

3dfb2773104c4907b684f572bf8fbabd.png

使用vue3 + OpenTiny UI + cesium 实现三维地球

  1. node.js >= v16.0

  2. opentiny vue3 ui安装指南 https://opentiny.design/tiny-vue/zh-CN/os-theme/docs/installation yarn add @opentiny/vue@3

项目依赖

"dependencies": {

    "@opentiny/vue": "3",

    "core-js": "^3.8.3",

    "vue": "^3.2.13",

    "vue-router": "4",

    "cesium": "^1.99.0",

    "cesium-navigation-es6": "^3.0.8"

  }

模块化代码

main.js

import { createApp } from 'vue'
import App from './App.vue'
// 引入 @opentiny/vue 组件
import TinyVue from '@opentiny/vue'
import Cesium from 'cesium'

// 创建并挂载根实例
const app = createApp(App)
// 注册 @opentiny/vue 组件
app.use(TinyVue)
app.use(Cesium)
app.mount('#app')

App.vue

<template>
  <gis></gis>
</template>

<script>
import gis from './components/EarthGis.vue'

export default {
  name: 'App',
  components: {
    gis
  },
  data() {
    return {
    }
  },
  mounted(){
    // 在“about:blank”中阻止脚本执行,因为文档的框架已被沙盒化并且未设置“allow-scripts”权限。
    let iframe = document.getElementsByClassName('cesium-infoBox-iframe')[0];
    iframe.setAttribute('sandbox', 'allow-same-origin allow-scripts allow-popups allow-forms');
    iframe.setAttribute('src', ''); // 必须设置src为空 否则不会生效。
  }
}
</script>

<style>
body {
  margin: 0;
  padding: 0;
  background-color: #e9edfa;
}
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  background-color: transparent;
}
#loading {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%);
  z-index: 1;
}
.progressText {
  text-align: center;
}
</style>

EarthGis.vue

<template>
  <div class="content">
      <tiny-layout :cols="12">
        <tiny-row :gutter="10">
          <tiny-col :span="12">
            <div class="col" style="position: relative;">
                <div class="select-menu">
                  <tiny-dropdown title="影像来源"  size="medium" split-button @item-click="selectChange">
                    <template #dropdown>
                      <tiny-dropdown-menu popper-class="select-item">
                        <tiny-dropdown-item
                          v-for="(item, index) in imageryLayersOptions"
                          :key="index"
                          :label="item.label"
                          :item-data="item.value"
                        ></tiny-dropdown-item>
                      </tiny-dropdown-menu>
                    </template>
                  </tiny-dropdown>
                </div>
                <div id="cesium-container"></div>
            </div>
          </tiny-col>
        </tiny-row>
      </tiny-layout>
  </div>
</template>

<script type="allow-scripts">
import 'cesium/Source/Widgets/widgets.css'
import {  Layout, Row, Col, Dropdown, DropdownMenu, DropdownItem } from '@opentiny/vue'
import { World } from './js/World/World.js'
export default {
  name: 'EarthGis',
  props: {
    msg: String
  },
  components: {
    TinyDropdown: Dropdown,
    TinyDropdownMenu: DropdownMenu,
    TinyDropdownItem: DropdownItem,
    TinyLayout: Layout,
    TinyRow: Row,
    TinyCol: Col
  },
  watch: {
    isLoading: function (val) {
      document.getElementById('loading').style.display = val ? 'black' : 'none'
    }
  },
  data() {
    return {
      isLoading: true,
      imageryLayersOptions: [{
        value: 'SingleTile',
        label: 'SingleTileImageryProvider'
      }],
      world: null
    }
  },
  methods: {
    selectChange(data) {
      let item = data.itemData
      switch (item) {
        case 'SingleTile':
          this.world.changeImagery()
          break
        default:
          break
      }
    }
  },
  mounted() {
    // 1. Create an instance of the World app
    this.world = new World('cesium-container');
    this.$nextTick(() => {
      this.selectChange({itemData: 'SingleTile'})
    })
  },
  destroy(){
    this.removeNavigation()
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#cesium-container{
  width: 100vw;
  height: 100vh;
}
.select-menu{
  position: absolute;
  top: 1rem;
  left: 1rem;
  background: #ffffff66;
  border-radius: 5px;
  padding: 10px;
}
.select-item{
  top: 1rem;
  left: 1rem;
  background: #ffffff66;
  border-radius: 5px;
  padding: 10px;
}
</style>

World.js

import { createViewer } from './components/viewer.js'
import { createImageryLayer } from './components/imageryLayer.js'
import { createTerrain } from './components/terrain.js'
import { createNavigation } from './components/navigation.js'
import { createCamera } from './components/camera.js';
import darkEarth from '@/assets/images/darkEarth.jpg'
import { FeatureDetection, 
    DirectionalLight, 
    Cartesian3, 
    JulianDate, 
    Math, 
    CameraEventType, 
    KeyboardEventModifier, 
    Cesium3DTileset,
    HeadingPitchRange,
    Matrix4,
    Cartographic,
    ScreenSpaceEventType,
    SingleTileImageryProvider,
    WebMercatorTilingScheme,
    ScreenSpaceEventHandler,
    WebMapTileServiceImageryProvider,
    GeographicTilingScheme,
    ImageryLayer, 
    UrlTemplateImageryProvider,
    OpenStreetMapImageryProvider,
    IonImageryProvider,
    createOsmBuildings,
    Rectangle  } from 'cesium'
// These variables are module-scoped: we cannot access them
// from outside the module
let viewer;
// 添加主题图层相关配置
let layerOption = {
  show: true, // 图像层是否可见
  alpha: 0.6, // 透明度
  nightAlpha: 1, // 地球夜晚一侧的透明度
  dayAlpha: 1, // 地球白天一侧的透明度
  brightness: 1, // 亮度
  contrast: 1, // 对比度
  hue: 0, // 色调
  saturation: 1, // 饱和度
  gamma: 1, // 伽马校正
}
class World {
    // 1. Create an instance of the World app
    constructor(id) {
        viewer = createViewer(id)
        viewer.imageryLayers.removeAll(true)
    }
    init(){
      // 修改场景环境,关闭相关特效
      viewer.scene.debugShowFramesPerSecond = true// 显示fps
      viewer.scene.moon.show = true// 月亮
      viewer.scene.fog.enabled = true// 雾
      viewer.scene.sun.show = true// 太阳
      viewer.scene.skyBox.show = true// 天空盒
      viewer.scene.globe.enableLighting = true // 激活基于太阳位置的光照(场景光照)
      viewer.resolutionScale = 1// 画面细度,默认值为1.0

      // 不显示cesium icon版权信息
      viewer._cesiumWidget._creditContainer.style.display="none"
      viewer.geocoder._form.children[0].placeholder = "请输入关键字"

      // DirectionalLight 表示 从无限远的地方向单一方向发射的光。解决模型光照问题
      viewer.scene.light = new DirectionalLight({
          direction: new Cartesian3(0.354925, -0.890918, -0.283358)
      })

      viewer.clock.currentTime = JulianDate.addHours(
          JulianDate.now(new Date()),
          12,
          new JulianDate()
      )
      // 启用深度测试,使地形后面的东西消失。
      viewer.scene.globe.depthTestAgainstTerrain = true
      viewer.scene.fxaa = false
      viewer.scene.postProcessStages.fxaa.enabled = true

      // 水雾特效
      viewer.scene.globe.showGroundAtmosphere = true

      // 设置最大俯仰角,[-90,0]区间内,默认为-30,单位弧度
      viewer.scene.screenSpaceCameraController.constrainedPitch = Math.toRadians(-20)
      viewer.scene.screenSpaceCameraController.autoResetHeadingPitch = false
      viewer.scene.screenSpaceCameraController.inertiaZoom = 0.5
      viewer.scene.screenSpaceCameraController.minimumZoomDistance = 50
      viewer.scene.screenSpaceCameraController.maximumZoomDistance = 20000000

      viewer.scene.screenSpaceCameraController.zoomEventTypes = [
          CameraEventType.RIGHT_DRAG,
          CameraEventType.WHEEL,
          CameraEventType.PINCH
      ]

      viewer.scene.screenSpaceCameraController.tiltEventTypes = [
          CameraEventType.MIDDLE_DRAG,
          CameraEventType.PINCH,
          {
              eventType: CameraEventType.LEFT_DRAG,
              modifier: KeyboardEventModifier.CTRL
          },
          {
              eventType: CameraEventType.RIGHT_DRAG,
              modifier: KeyboardEventModifier.CTRL
          }
      ]

      // 开启抗锯齿
      if (FeatureDetection.supportsImageRenderingPixelated()) {
          // 判断是否支持图像渲染像素化处理
          viewer.resolutionScale = window.devicePixelRatio
      }
      // 添加默认图层
      createImageryLayer()
      // 开启Navigation导航插件
      createNavigation(viewer)
      // 添加cesium自带的地形
      createTerrain(viewer)

      // 将三维球定位到中国
      viewer.camera.flyTo({
          destination: Cartesian3.fromDegrees(103.84, 31.15, 17860000),
          orientation: {
          heading: Math.toRadians(348.4202942851978),
          pitch: Math.toRadians(-89.74026687972041),
          roll: Math.toRadians(0)
          },
          complete: () => {
              // 定位完成之后的回调函数
              console.log('定位完成')
              document.getElementById('loading').style.display = 'none'
          }
      })

      // 设置默认的视角为中国
      createCamera.DEFAULT_VIEW_RECTANGLE = Rectangle.fromDegrees(
          // 西边经度
          89.5,
          // 南边维度
          20.4,
          // 东边经度
          110.4,
          // 北边维度
          61.2
      )

      //this.cion(layerOption)
      //this.osm(layerOption)
      this.hot(layerOption)
      //this.cartoVoyager(layerOption)
      //this.cartoDark(layerOption)
      //this.stamen(layerOption)
      //this.wmtsImages(layerOption)
      //this.osmBuildings()

      // const tilesetOption = {
      //     skipLevelOfDetail: true,
      //     baseScreenSpaceError: 1024,
      //     skipScreenSpaceErrorFactor: 16,
      //     skipLevels: 1,
      //     immediatelyLoadDesiredLevelOfDetail: false,
      //     loadSiblings: false,
      //     cullWithChildrenBounds: true
      // }

      // const modelPromise = this.addThreeDTiles(69380, tilesetOption);
      // modelPromise.then(model => {
      //     console.log('tileset: ', model)
      //     this.setPosition(model, 113.27, 23.13, 10) // 调整位置到,高度10米
      //     this.setPosition(model, undefined, undefined, 500) // 仅修改高度至500米
      //     this.serMatrix(model) // 使用默认变换矩阵(单位向量),实现回到默认位置的效果
      // })
    }
    // 切换图层
    changeImagery() {
      viewer.imageryLayers.removeAll(true)
      this.roaming()
    }
    async addThreeDTiles(url, option) {
      // 开启地形深度检测:
      // 控制在渲染场景时,相机是否进行深度测试以避免将被遮挡的物体绘制在前景
      // true: 相机会根据地形高度信息进行深度测试,避免将低于地面的物体绘制在地面之上
      viewer.scene.globe.depthTestAgainstTerrain = true

      let tileset = {}
      if (typeof url == 'number') {
        tileset = await Cesium3DTileset.fromIonAssetId(url, option);
      } else {
        tileset = await Cesium3DTileset.fromUrl(url, option);
      }

      viewer.scene.primitives.add(tileset);
      // 定位到模型
      viewer.zoomTo(
        tileset,
        new HeadingPitchRange(
          0.0,
          -0.5,
          tileset.boundingSphere.radius * 2.0 // 模型的包围球半径的2倍
        )
      )
      return tileset // 返回模型对象
    }
    setPosition(tileset, lng, lat, h) {
      // 计算出模型包围球的中心点(弧度制),从世界坐标转弧度制
      const cartographic = Cartographic.fromCartesian(
        tileset.boundingSphere.center
      )
      const { longitude, latitude, height } = cartographic

      // 模型包围球的中心点坐标,输出以笛卡尔坐标系表示的三维坐标点
      const current = Cartesian3.fromRadians(
        longitude,
        latitude,
        height
      )
      // 新的位置的中心点坐标,输出以笛卡尔坐标系表示的三维坐标点
      const offset = Cartesian3.fromDegrees(
        lng || Math.toDegrees(longitude),
        lat || Math.toDegrees(latitude),
        h || height
      );

      // 计算差向量:计算tileset的平移量,并将其应用到modelMatrix中
      const translation = Cartesian3.subtract(
        offset,
        current,
        new Cartesian3()
      )

      // 修改模型的变换矩阵,通过四维矩阵
      tileset.modelMatrix = Matrix4.fromTranslation(translation);
      viewer.zoomTo(tileset);
    }
    //Resets the position of a tileset to a specified model matrix or the identity matrix if none is provided.
    serMatrix(tileset, matrix) {
      tileset.modelMatrix = matrix || Matrix4.IDENTITY
      viewer.zoomTo(tileset);
    }
    showAllImagery(boolean = true) {
      // 获取图像图层集合
      const imageryLayers = viewer.imageryLayers;

      // 遍历图像图层并隐藏它们
      let numLayers = imageryLayers.length;
      for (let i = 0; i < numLayers; i++) {
        const layer = imageryLayers.get(i); // 获取图像图层对象
        layer.show = boolean; // 设置图像图层隐藏
      }
    }
    async roaming() {
      let isRoaming = true; // 漫游标志位
      const DEFAULT_LIGHTING = viewer.scene.globe.enableLighting; // 默认光照状态
      const DEFAULT_SKY_ATMOSPHERE = viewer.scene.skyAtmosphere.show; // 默认光照状态
      let bgImglayer; // 地球底图

      this.showAllImagery(false); // 隐藏所有图层
      viewer.clock.multiplier = -2000.0;  // 时间加速

      const provider = await SingleTileImageryProvider.fromUrl(darkEarth);
 
      provider._tilingScheme = new WebMercatorTilingScheme()
      bgImglayer = viewer.imageryLayers.addImageryProvider(provider); // 加载背景底图

      if (!DEFAULT_LIGHTING) {
        viewer.scene.globe.enableLighting = true; // 开启光照
      }
      if (!DEFAULT_SKY_ATMOSPHERE) {
        viewer.scene.skyAtmosphere.show = true; // 开启天空大气,能在一定程度上降低地球轮廓锯齿
      }

      // 添加鼠标事件,触发后停止漫游效果
      const handler = new ScreenSpaceEventHandler(viewer.scene.canvas); // 交互句柄
      handler.setInputAction(() => {
        isRoaming = false // 停止旋转
        this.showAllImagery(true) // 显示图层
        if (!DEFAULT_LIGHTING) {
          viewer.scene.globe.enableLighting = false; // 关闭光照
        }
        if (!DEFAULT_SKY_ATMOSPHERE) {
          viewer.scene.skyAtmosphere.show = false; // 关闭光照
        }
        viewer.imageryLayers.remove(bgImglayer, true); // 移除图层
        viewer.clock.multiplier = 1;  // 正常时间流速

        handler.removeInputAction(ScreenSpaceEventType.LEFT_CLICK); // 移除鼠标事件监听
        this.init()
      }, ScreenSpaceEventType.LEFT_CLICK);

      (function roamingEvent() {
        if (isRoaming) {
          // 控制相机围绕 Z 轴旋转
          viewer.camera.rotate(Cartesian3.UNIT_Z, Math.toRadians(0.1));
          requestAnimationFrame(roamingEvent);
        }
      })()
    }
    // Cesium ION 服務
    cion (layerOption, id = 3812)  {
      const layer = new ImageryLayer(
        new IonImageryProvider({ assetId: id }),
        layerOption
      )
      viewer.imageryLayers.add(layer)
      return layer
    }
    // 加载osm地图
    osm (layerOption)  {
      const layer = new ImageryLayer(
        new OpenStreetMapImageryProvider({ url: 'https://a.tile.openstreetmap.org/' }),
        layerOption
      )
      viewer.imageryLayers.add(layer)
      return layer
    }
    // 加载Humanitarian OpenStreetMap Team style地图
    hot (layerOption)  {
      const layer = new ImageryLayer(
        new UrlTemplateImageryProvider({ url: 'https://tile-{s}.openstreetmap.fr/hot/{z}/{x}/{y}.png', subdomains: ['a', 'b', 'c'] }),
        layerOption
      )
      viewer.imageryLayers.add(layer)
      return layer
    }
    // 加载carto Basemaps 航海风格地图
    cartoVoyager (layerOption)  {
      const layer = new ImageryLayer(
        new UrlTemplateImageryProvider({ url: 'https://basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png' }),
        layerOption
      )
      viewer.imageryLayers.add(layer)
      return layer
    }
    // 加载carto Basemaps 黑暗风格地图
    cartoDark (layerOption)  {
      const layer = new ImageryLayer(
        new UrlTemplateImageryProvider({ url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', subdomains: ['a', 'b', 'c', 'd'] }),
        layerOption
      )
      viewer.imageryLayers.add(layer) 
      return layer
    }
    // 加载Stamen地图
    stamen (layerOption) {
      const layer = new ImageryLayer(
        new UrlTemplateImageryProvider({ url: 'https://stamen-tiles.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.png' }),
        layerOption
      )
      viewer.imageryLayers.add(layer)
      return layer
    }
    // 加载WMTS瓦片地图服务
    wmtsImages () {
      // EPSG:900913(标准名为EPSG:3875)网格切分的瓦片。当将tileMatrixSetID设置为 'EPSG:4326',访问常用的EPSG:4326网络的瓦片
      // 访问GeoServer发布的地图瓦片服务 WebMapTileServiceImageryProvider的切片方案tilingScheme默认使用EPSG:3875投影,即伪墨卡托网格访问切片,与EPSG:4326网格的切片方案存在较大差异
      // Tiling是一种椭球体表面上的几何图形或图像的平铺方案。在详细级别为0,即最粗、最不详细的级别上,瓦片的数量是可配置的。在详细级别为1级以上,每个是一级级瓦片经纬两个方向上扩展为两个瓦片,共有四个子瓦片。如此扩展到最大的缩放级别,这也构成了一个图像瓦片的金字塔。TillingScheme有一个参数ellipsoid用来决定切处时使用的椭球,另外两个比较重要的参数numberOfLevelZeroTilesX和numberOfLevelZeroTilesY,用来决定0级瓦片的数量。
      // TilingSchemee有两个子类,为WebMercatorTilingScheme和GeographicTilingScheme。其中WebMercatorTilingScheme对应于EPSG:3857切片方案,常见于谷歌地图、微软必应地图以及大多数的ArcGIS在线地图,也是Cesium中默认的切片方案。
      // GeographicTilingScheme对应于EPSG:4326切片方案,是一个简单的地理投影方案,可直接将经纬度映射为X和Y,这种投影通常被称为地理投影、等矩形投影、等距圆柱形投影等。
      // 由于在X方向上,WebMercatorTilingScheme只有一个0级瓦片,而GeographicTilingScheme却有2个,这就导致了默认的EPSG:3857切片方案不能正确加载EPSG:4326切片方案的瓦片图像。

      let layer = new WebMapTileServiceImageryProvider({
          url : '/map/gwc/service/wmts/rest/xian:satellite/{style}/{TileMatrixSet}/{TileMatrixSet}:{TileMatrix}/{TileRow}/{TileCol}?format=image/png',
          style : 'raster',
          tileMatrixSetID : 'EPSG:4326',
          tilingScheme: new GeographicTilingScheme(),
      });
      viewer.imageryLayers.addImageryProvider(layer);
      return layer
    }
    // 载入OSM建筑物
    osmBuildings = () => {
      // 突出显示所有的商业和住宅建筑,以查看整个城市不同社区的模式
      // Cesium OSM 建筑物通过3D Tiles,它可以在web上高效地流式传输和可视化。
      // 3D Tiles是一个开放的标准,所以Cesium OSM建筑可以在任何兼容它的查看器中使用,不仅仅是开源的Cesium。
      // Cesium全球3.5亿做建筑物,数据来源openStreetMap地图

      //OpenStreetMap(简称OSM,中文是公开地图)是一个网上地图协作计划,目标是创造一个内容自由且能让所有人编辑的世界地图。
      //其包含图层主要有高速公路、铁路、水系、水域、建筑、边界、建筑物等图层。我们不仅能够免费下载城市数据还可以下载全球数据。
      //网址为https://www.openstreetmap.org/
      //Cesium中支持使用OSM在线的建筑矢量三维模型,但目前OSM数据在国外较为细致,国内只支持几个大城市。
      //由于OSM建筑数据量大,加载较慢,用户在使用建筑白膜时,可根据需求,在OSM官网或百度、高德等地图服务商中下载建筑矢量数据,
      //使用ArcGIS等GIS软件和SketchUP等建模软件,生成建筑白膜,并使用建模软件对白膜进行贴图修改等操作,以实现城市建筑的美化,
      //使用CesiumLab等软件对建模的三维建筑数据 进行切片生成3Dtiles等Cesium支持的数据类型,对其进行加载使用。
      const addOSMAsync = () => {
        try {
          // 突出显示所有的商业和住宅建筑,以查看整个城市不同社区的模式
          viewer.scene.primitives.add(createOsmBuildings())
        } catch (error) {
          console.log(`Failed to add world imagery: ${error}`);
        }
      };
      addOSMAsync()
    }
}
    
export { World };

viewer.js

import { Viewer, Ion } from 'cesium'
function createViewer(id) {
    const cesiumToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmNDVhMjQ0Yi05MDg4LTRlNDYtYTIxMi00YmI4ZWYxOWMyNTgiLCJpZCI6MTQ5MzYwLCJpYXQiOjE2ODc3ODQ0OTh9.KlhT_LCnsEtYyawpEmJ_wx44_qTUbgze-SxGMRavbAM'
    Ion.defaultAccessToken = cesiumToken
    const viewerOption = {
        // 默认隐藏
        infoBox: true, //是否显示信息框
        animation:false,    //左下角的动画仪表盘
        baseLayerPicker:true,  //右上角的图层选择按钮
        geocoder:true,  //搜索框
        homeButton:true,  //home按钮
        sceneModePicker:true, //模式切换按钮
        timeline:true,    //底部的时间轴
        navigationHelpButton:true,  //右上角的帮助按钮
        fullscreenButton:true,   //右下角的全屏按钮
        contextOptions:{
          webgl:{
            alpha:true
          }
        }
    }
    const instance = new Viewer(id, viewerOption);
    return instance;
}

export { createViewer }

imageryLayer.js

import { ImageryLayer, UrlTemplateImageryProvider } from 'cesium'
// 添加主题图层相关配置
let layerOption = {
    show: true, // 图像层是否可见
    alpha: 0.6, // 透明度
    nightAlpha: 1, // 地球夜晚一侧的透明度
    dayAlpha: 1, // 地球白天一侧的透明度
    brightness: 1, // 亮度
    contrast: 1, // 对比度
    hue: 0, // 色调
    saturation: 1, // 饱和度
    gamma: 1, // 伽马校正
}
function createImageryLayer( option=layerOption ) {
    // 添加主题图层相关配置
    const instance = new ImageryLayer(
        new UrlTemplateImageryProvider({ url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', subdomains: ['a', 'b', 'c', 'd'] }),
        option
    )
    return instance;
}

export { createImageryLayer }

camera.js

import { Camera } from 'cesium'
function createCamera() {
    const instance = Camera;
    return instance;
}

export { createCamera }

terrain.js

import { createWorldTerrainAsync } from 'cesium'
function createTerrain(viewer) {
    // 添加地形数据
    const addWorldTerrainAsync = async () => {
        try {
          const terrainProvider = await createWorldTerrainAsync({
            requestWaterMask: false, // 水面特效
            requestVertexNormals: true // 地形照明
          });  
          viewer.terrainProvider = terrainProvider;
        } catch (error) {
          console.log(`Failed to add world imagery: ${error}`);
        }
    };
    addWorldTerrainAsync()
}

export { createTerrain }

navigation.js

import CesiumNavigation from 'cesium-navigation-es6'
import { Cartographic } from 'cesium'

let instance;
function createNavigation(viewer) {
    let navigationOptions = {};
    // 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是Cesium.Cartographic 和Cesium.Rectangle.
    navigationOptions.defaultResetView = Cartographic.fromDegrees(103.84, 31.15, 17860000);
    // 用于启用或禁用罗盘。true是启用罗盘,false是禁用罗盘。默认值为true。如果将选项设置为false,则罗盘将不会添加到地图中。
    navigationOptions.enableCompass= true;
    // 用于启用或禁用缩放控件。true是启用,false是禁用。默认值为true。如果将选项设置为false,则缩放控件 将不会添加到地图中。
    navigationOptions.enableZoomControls= true;
    // 用于启用或禁用距离图例。true是启用,false是禁用。默认值为true。如果将选项设置为false,距离图例将不会添加到地图中。
    navigationOptions.enableDistanceLegend= true;
    // 用于启用或禁用指南针外环。true是启用,false是禁用。默认值为true。如果将选项设置为false,则该环将可见但无效。
    navigationOptions.enableCompassOuterRing= true;
    navigationOptions.resetTooltip = "重置";
    navigationOptions.zoomInTooltip = "放大";
    navigationOptions.zoomOutTooltip = "缩小";
    // 开启Navigation 罗盘、图例、指南针等导航插件
    instance = new CesiumNavigation(viewer, navigationOptions);
    return instance;
}
function removeNavigation(){
    instance.destroy();
}

export { createNavigation, removeNavigation }

NASA夜色中的地球图片

9f7a40342aee4771a15c49e75cce9216.png

参见:

运营系统

分享Cesium.js Web 三维地球-CSDN博客

  • 26
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue2是一种流行的JavaScript框架,用于构建用户界面。它具有轻量级、高效和灵活的特点,可以帮助开发者快速构建交互性强的Web应用程序。 Element UI是一套基于Vue2的开源UI库,提供了一系列的组件,包括按钮、表格、表单等,方便开发者构建美观的前端界面。 Cesium是一个用于构建地球图像的JavaScript库,可以在Web上创建高度交互的3D地球视图。它提供了丰富的地理信息和可视化功能,可以用于制作地理信息系统(GIS)应用程序。 搭建Vue2、Element UICesium的框架可以让开发者在Web应用程序中结合地理信息和用户界面。具体步骤如下: 1. 首先,在项目中安装Vue2、Element UICesium的依赖项。 ``` npm install vue npm install element-ui npm install cesium ``` 2. 在Vue项目中引入Vue2和Element UI的库,可以使用CDN或本地引入的方式。 3. 创建一个Vue的根组件,并在模板中使用Element UI的组件。 4. 在Vue项目中引入Cesium的库,可以使用CDN或本地引入的方式。 5. 在Vue的根组件中,创建一个Cesium的容器,并在created生命周期钩子函数中初始化Cesium地球视图。 6. 在Cesium地球视图中加载地理信息和相应的可视化效果,例如加载地图数据、添加3D模型等。 通过以上步骤,就可以搭建一个基于Vue2、Element UICesium的框架。开发者可以根据自己的需求进一步开发和定制化。这个框架可以让开发者在用户界面上展示地理信息,并提供交互性强的地球视图。同时,也可以使用Element UI的组件提供更美观友好的用户界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值