首页 > 其他分享 >分享:vue3+OpenTiny UI+cesium 实现三维地球

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

时间:2024-03-24 17:00:27浏览次数:27  
标签:layer const viewer scene UI vue3 cesium new true

效果图

使用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 }

夜色中的地球图片

标签:layer,const,viewer,scene,UI,vue3,cesium,new,true
From: https://blog.csdn.net/david_232656/article/details/136971486

相关文章

  • 7.2 文件的特殊权限:suid sgid sticky和文件扩展权限ACL
    文件的特殊权限:suidsgidsticky和文件扩展权限ACL其实文件与目录设置不止这些,还有所谓的特殊权限。由于特殊权限会拥有一些`特权`特殊权限:7.2.1文件的特殊权限:suidsgidsticky7.2.1.1SUID(setuid设置用户ID):限定:只能设置在二进制可执行......
  • 百度千帆AppBuilder连夜上的新3款应用体验:封神智读助手、西游取经指南、今日说法,“今
    千帆AppBuilder的应用中心连夜上新了3款应用,分别是封神智读助手、西游取经指南、今日说法封神智读助手:顾名思义是《封神》智读助手,回答用户关于《封神演义》的问题。会根据知识库中的内容回答用户的问题,并优先进行知识库搜索。如果知识库中没有相关内容,会调用百度搜索接......
  • vue3项目初始化
    初始化项目newsappVSCode打开终端,newsapp项目目录,可自定义vuecreatenewsapp有提示“因为在此系统上禁止运行脚本”的话,请执行set-ExecutionPolicyRemoteSigned执行后再重复执行vuecreatenewsapp注意选择Vue3版本测试项目是否正常可运行:先进入newsapp目录,用cdn......
  • 前端Vue篇之Vue3响应式:Ref和Reactive
    目录Vue3响应式:Ref和ReactiveRef和Reactive概述用途Ref基本用法及在setup()中的使用基本用法在setup()中使用`<scriptsetup>`语法为何使用refReactive基本概念及在模板中的使用基本概念在模板中使用Reactive深层响应式与Ref区别为何使用ReactiveRef和Reactive比较和......
  • Centos7 安装MySQL8后 加装 MySQL基准测试套件 (MySQL Benchmark Suite)
    CentOS7中安装MySQL8.3.0没有/usr/share/mysql/sql-bench下的BenchmarkSuite工具1.yum安装epel源yum-yinstallepel-release2.安装perl平台yum-yinstallperl*3.获得/usr/share/mysql/sql-benchwgethttps://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.......
  • Blazor整合layui
    复制layui文件夹到wwwroot文件夹中:razor组件中引入js文件和css文件:@page"/user"@[email protected]@injectUserServicemyUserService<linkhref="/layui/css/layui.css"rel="stylesheet"><scriptsrc="/......
  • C# GUI_Async_await异步报告
    //.net8环境WinformnamespaceGUI_Async_await异步报告_供参考_{publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}privatevoidbutton1_Click(objectsender,EventArgse)......
  • 使用hbuilderX开发小程序遇到的坑
    第一,微信小程序编译每次都出现[project.config.json文件内容错误]project.config.json:libVersion字段需为string解决办法第二,修改了pages文件夹的.vue页面发现页面空白没生效原因:修改要记得保存第三, 微信开发者工具中报错:routeDonewithawebviewId2thati......
  • 鸿蒙HarmonyOS实战-ArkUI组件(Stack)
    ......
  • [MAUI]集成高德地图组件至.NET MAUI Blazor项目
    @目录前期准备:注册高德开发者并创建key登录控制台创建key获取key和密钥创建项目创建JSAPILoader配置权限创建定义创建模型创建地图组件创建交互逻辑项目地址地图组件在手机App中常用地理相关业务,如查看线下门店,设置导航,或选取地址等。是一个较为常见的组件。在.NETMAUI......