在vite创建的vue3项目中使用Cesium加载czml路径信息和无人机模型

奋斗吧
奋斗吧
擅长邻域:未填写

标签: 在vite创建的vue3项目中使用Cesium加载czml路径信息和无人机模型

2023-07-13 18:23:35 134浏览

在vite创建的vue3项目中使用Cesium加载czml路径信息和无人机模型

在vite创建的vue3项目中使用Cesium加载czml路径信息和无人机模型

  1. 使用vite创建vue3项目

    npm create vite@latest
    

    cd到创建的项目文件夹中

    npm install
    

    安装Cesium

    npm i cesium vite-plugin-cesium vite -D
    
  2. 配置

    1. vite.config.js文件:添加Cesium并设置反向代理实现跨域。

      import { defineConfig } from 'vite'
      import vue from '@vitejs/plugin-vue'
      import cesium from 'vite-plugin-cesium';
      export default defineConfig({
        plugins: [vue(), cesium()],
        //设置反向代理,跨域
        server: {
          proxy: {
            '/ArcGIS': {
              target: 'https://services.arcgisonline.com',//代理的地址
              changeOrigin: true,
            }
          }
        }
      });
      
    2. style.css(可选):修改#app样式

      #app {
      		  max-width: 100%;
      		  margin: 0 auto;
      		  padding: 2rem;
      		  text-align: center;
      		}
      
  3. 代码

    1. App.vue

      <template>
        <div id="cesiumContainer"></div>
      </template>
      
      <script setup>
      import * as Cesium from 'cesium';
      import { onMounted } from 'vue';
      onMounted(async () => {
      
        // 相当于密钥,申请使用下边链接中的数据时需要用到
        Cesium.Ion.defaultAccessToken = '你的token';
        Cesium.ArcGisMapService.defaultAccessToken = '你的token';
      
      
        let viewer = new Cesium.Viewer('cesiumContainer', {
          // 防止报错
          infoBox: false,
          // 去掉右上角的一个小选项卡
          baseLayerPicker: false,
          // 加载世界街道地图的底图
          baseLayer: Cesium.ImageryLayer.fromProviderAsync(
            Cesium.ArcGisMapServerImageryProvider.fromUrl("/ArcGIS/rest/services/World_Street_Map/MapServer")
          ),
          // 三维立体效果、水波纹
          terrainProvider: await Cesium.createWorldTerrainAsync({
            requestVertexNormals: true,
            requestWaterMask: true
          })
        });
      
        viewer.camera.setView({
          // 初始的相机的定位 定在纽约
          destination: new Cesium.Cartesian3(1332761, -4662399, 4137888),
          // 方向 俯仰
          orientation: {
            heading: 0.6,
            pitch: -0.66
          }
        });
      
        // 添加纽约建筑模型
        let city = viewer.scene.primitives.add(
          await Cesium.Cesium3DTileset.fromIonAssetId(75343)
        );
      
        // 定义建筑的3D样式 层次分明
        city.style = new Cesium.Cesium3DTileStyle({
          color: {
            // 条件判断建筑具体的颜色
            conditions: [
              ['${Height} >= 300', 'rgba(45,0,75,0.5)'],
              ['${Height} >= 200', 'rgb(102,71,151)'],
              ['${Height} >= 100', 'rgba(170,162,204,0.5)'],
              ['${Height} >= 50', 'rgba(224,226,238,0.5)'],
              ['${Height} >= 25', 'rgba(252,230,200,0.5)'],
              ['${Height} >= 10', 'rgba(248,176,87,0.5)'],
              ["true", 'rgb(127,59,8)']
            ]
          }
        })
      
      
        // 邻域边界的加载
        let neighborhoodsPromise = Cesium.GeoJsonDataSource.load('./assets/SampleData/sampleNeighborhoods.geojson');
        // 贴在地图表面
        neighborhoodsPromise.then((dataSource) => {
          // 将数据添加到查看器
          viewer.dataSources.add(dataSource);
          // 把数据进行着色的调整以及放到地图的表面
          // 拿到区域的实例  Get the array of entities
          let neighborhoodsEntities = dataSource.entities.values;
          for (let i = 0; i < neighborhoodsEntities.length; i++) {
            let entity = neighborhoodsEntities[i];
            // 判断存不存在相应的图形
            if (Cesium.defined(entity.polygon)) {
              entity.name = entity.properties.neighborhood;
              // 设置多边形颜色
              entity.polygon.material = Cesium.Color.fromRandom({
                red: 0.1,
                maximumGreen: 0.5,
                minimumBlue: 0.5,
                alpha: 0.6
              });
              // 设置地形着色
              entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;
              // 设置位置 贴到多边形最底下
              // 生成多边形中心
              let polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;
              // 椭球体
              entity.position = Cesium.Ellipsoid.WGS84.scaleToGeocentricSurface(
                // 边界球
                Cesium.BoundingSphere.fromPoints(polyPositions).center
              );
      
              // 生成标签
              entity.label = {
                text: entity.name,
                showBackground: true,
                scale: 0.6,
                horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                // 设置显示的距离范围
                distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10, 8000),
                // 禁用的距离
                disableDepthTestDistance: 100
              }
            }
          }
        });
      
        // 地图标记显示
        let kmloptions = {
          camera: viewer.scene.camera,
          canvas: viewer.scene.canvas,
          // 如果我们想要将几何特征(多边形、线串和线性环)固定在地面上,则为true
          clampToGround: true
        };
        // KML文件时谷歌公司创建的一个地标性文件,用于记录某一地点、或者连续地点的时间、经纬度、海拔等地理信息数据
        let geoCachePromise = Cesium.KmlDataSource.load('./assets/SampleData/sampleGeocacheLocations.kml', kmloptions);
        // 将geocache广告牌实体添加到场景中并为其设置样式
        geoCachePromise.then((dataSource) => {
          // console.log(dataSource)
          // 将新数据作为实体添加到查看器
          viewer.dataSources.add(dataSource);
          // 获取实体数组
          let geoCacheEntities = dataSource.entities.values;
      
          for (let i = 0; i < geoCacheEntities.length; i++) {
            let entity = geoCacheEntities[i];
            if (Cesium.defined(entity.billboard)) {
              // 调整垂直原点,使图钉位于地形上
              entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
              entity.billboard.image = '/assets/tagpark.png';
              // 禁用标签以减少混乱
              entity.label = undefined;
              // 添加距离现实条件
              entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10, 20000);
              // 以度为单位计算经度和纬度
              let cartographicPosition = Cesium.Cartographic.fromCartesian(entity.position.getValue(Cesium.JulianDate.now()));
              let latitude = Cesium.Math.toDegrees(cartographicPosition.latitude);
              let longtitude = Cesium.Math.toDegrees(cartographicPosition.longitude);
              // 修改描述
              let description = '<table class="cesium-infoBox-defaultTable cesium-infoBox-defaultTable-lighter"><tbody>' +
                '<tr><th>' + "longtitude" + '</th><td>' + longtitude.toFixed(5) + '</td></tr>' +
                '<tr><th>' + "latitude" + '</th><td>' + latitude.toFixed(5) + '</td></tr>' +
                '<tr><th>' + "实时人流" + '</th><td>' + Math.floor(Math.random() * 20000) + '</td></tr>' +
                '<tr><th>' + "安全等级" + '</th><td>' + Math.floor(Math.random() * 5) + '</td></tr>' +
                '</tbody></table>';
              entity.description = description;
            }
          }
        })
      
        // 从czml文件中加载飞行路径
        let dronePromise = Cesium.CzmlDataSource.load('./assets/SampleData/sampleFlight.czml');
        // 无人机实体
        dronePromise.then((dataSource) => {
          // 添加获取到的实体数据
          viewer.dataSources.add(dataSource);
          // 通过ID获取轨迹的实体
          let drone = dataSource.entities.getById('Aircraft/Aircraft1');
          // 设置无人机实体的模型
          drone.model = {
            // CesiumDrone.gltf会报错
            // uri:'./assets/SampleData/Models/CesiumDrone.gltf',
      
            uri: './assets/SampleData/Models/Cesium_Air.glb',
            // uri:'./assets/SampleData/Models/ferrari2.gltf',
            // 设置模型最小的时候的像素大小 缩小地球的时候也能看到
            minimumPixelSize: 128,
            // 设置最大规格
            maximumScale: 500,
            // 轮廓的颜色属性
            silhouetteColor: Cesium.Color.WHITE,
            // 指定轮廓的大小
            silhouetteSize: 0
          }
          // 设置无人机的方向 角度
          drone.orientation = new Cesium.VelocityOrientationProperty(drone.position);
          // 设置当前所在的具体的位置
          drone.viewFrom = new Cesium.Cartesian3(0, -30, 30);
          // 设置动起来
          viewer.clock.shouldAnimate = true;
        })
      })
      </script>
      
      <style>
      html,
      body,
      #app,
      #cesiumContainer {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden;
      }
      </style>
      
      
    2. 解读

      1. 加载token

        // 相当于密钥,申请使用下边链接中的数据时需要用到
        Cesium.Ion.defaultAccessToken = '你的token';
        Cesium.ArcGisMapService.defaultAccessToken = '你的token';
        
      2. 创建查看器viewer,加载世界街道地图,注意vite.config.js中配合的跨域。

          let viewer = new Cesium.Viewer('cesiumContainer', {
            // 防止报错
            infoBox: false,
            // 去掉右上角的一个小选项卡
            baseLayerPicker: false,
            // 加载世界街道地图的底图
            baseLayer: Cesium.ImageryLayer.fromProviderAsync(
              Cesium.ArcGisMapServerImageryProvider.fromUrl("/ArcGIS/rest/services/World_Street_Map/MapServer")
            ),
            // 三维立体效果、水波纹
            terrainProvider: await Cesium.createWorldTerrainAsync({
              requestVertexNormals: true,
              requestWaterMask: true
            })
          });
        
      3. 初始化相机位置

        viewer.camera.setView({
            // 初始的相机的定位 定在纽约
            destination: new Cesium.Cartesian3(1332761, -4662399, 4137888),
            // 方向 俯仰
            orientation: {
              heading: 0.6,
              pitch: -0.66
            }
          });
        
      4. 添加纽约建筑模型并设置建筑颜色样式

        // 添加纽约建筑模型
          let city = viewer.scene.primitives.add(
            await Cesium.Cesium3DTileset.fromIonAssetId(75343)
          );
        
          // 定义建筑的3D样式 层次分明
          city.style = new Cesium.Cesium3DTileStyle({
            color: {
              // 条件判断建筑具体的颜色
              conditions: [
                ['${Height} >= 300', 'rgba(45,0,75,0.5)'],
                ['${Height} >= 200', 'rgb(102,71,151)'],
                ['${Height} >= 100', 'rgba(170,162,204,0.5)'],
                ['${Height} >= 50', 'rgba(224,226,238,0.5)'],
                ['${Height} >= 25', 'rgba(252,230,200,0.5)'],
                ['${Height} >= 10', 'rgba(248,176,87,0.5)'],
                ["true", 'rgb(127,59,8)']
              ]
            }
          })
        
      5. 划分城市区域并着色

        // 邻域边界的加载
          let neighborhoodsPromise = Cesium.GeoJsonDataSource.load('./assets/SampleData/sampleNeighborhoods.geojson');
          // 贴在地图表面
          neighborhoodsPromise.then((dataSource) => {
            // 将数据添加到查看器
            viewer.dataSources.add(dataSource);
            // 把数据进行着色的调整以及放到地图的表面
            // 拿到区域的实例  Get the array of entities
            let neighborhoodsEntities = dataSource.entities.values;
            for (let i = 0; i < neighborhoodsEntities.length; i++) {
              let entity = neighborhoodsEntities[i];
              // 判断存不存在相应的图形
              if (Cesium.defined(entity.polygon)) {
                entity.name = entity.properties.neighborhood;
                // 设置多边形颜色
                entity.polygon.material = Cesium.Color.fromRandom({
                  red: 0.1,
                  maximumGreen: 0.5,
                  minimumBlue: 0.5,
                  alpha: 0.6
                });
                // 设置地形着色
                entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;
                // 设置位置 贴到多边形最底下
                let polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;
                entity.position = Cesium.Ellipsoid.WGS84.scaleToGeocentricSurface(
                  Cesium.BoundingSphere.fromPoints(polyPositions).center
                );
        
                // 生成标签
                entity.label = {
                  text: entity.name,
                  showBackground: true,
                  scale: 0.6,
                  horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                  verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                  // 设置显示的距离范围
                  distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10, 8000),
                  // 禁用的距离
                  disableDepthTestDistance: 100
                }
              }
            }
          })
        
      6. 利用KML文件实现在地图上标记地点

        // 地图标记显示
          let kmloptions = {
            camera: viewer.scene.camera,
            canvas: viewer.scene.canvas,
            // 如果我们想要将几何特征(多边形、线串和线性环)固定在地面上,则为true
            clampToGround: true
          };
          // KML文件时谷歌公司创建的一个地标性文件,用于记录某一地点、或者连续地点的时间、经纬度、海拔等地理信息数据
          let geoCachePromise = Cesium.KmlDataSource.load('./assets/SampleData/sampleGeocacheLocations.kml', kmloptions);
          // 将geocache广告牌实体添加到场景中并为其设置样式
          geoCachePromise.then((dataSource) => {
            // console.log(dataSource)
            // 将新数据作为实体添加到查看器
            viewer.dataSources.add(dataSource);
            // 获取实体数组
            let geoCacheEntities = dataSource.entities.values;
        
            for (let i = 0; i < geoCacheEntities.length; i++) {
              let entity = geoCacheEntities[i];
              if (Cesium.defined(entity.billboard)) {
                // 调整垂直原点,使图钉位于地形上
                entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
                entity.billboard.image = '/assets/tagpark.png';
                // 禁用标签以减少混乱
                entity.label = undefined;
                // 添加距离现实条件
                entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10, 20000);
                // 以度为单位计算经度和纬度
                let cartographicPosition = Cesium.Cartographic.fromCartesian(entity.position.getValue(Cesium.JulianDate.now()));
                let latitude = Cesium.Math.toDegrees(cartographicPosition.latitude);
                let longtitude = Cesium.Math.toDegrees(cartographicPosition.longitude);
                // 修改描述
                let description = '<table class="Cesium-infoBox-defaultTable cesium-infoBox-defaultTable-lighter"><tbody>' +
                  '<tr><th>' + "longtitude" + '</th><td>' + longtitude.toFixed(5) + '</td><tr>' +
                  '<tr><th>' + "latitude" + '</th><td>' + latitude.toFixed(5) + '</td><tr>' +
                  '<tr><th>' + "实时人流" + '</th><td>' + Math.floor(Math.random() * 20000) + '</td><tr>' +
                  '<tr><th>' + "安全等级" + '</th><td>' + Math.floor(Math.random() * 5) + '</td><tr>' +
                  '</tbody><table>';
                entity.description = description;
              }
            }
          })
        
      7. 加载飞行路径和飞机模型

          // 从czml文件中加载飞行路径
          let dronePromise = Cesium.CzmlDataSource.load('./assets/SampleData/sampleFlight.czml');
          // 无人机实体
          dronePromise.then((dataSource) => {
            // 添加获取到的实体数据
            viewer.dataSources.add(dataSource);
            // 通过ID获取轨迹的实体
            let drone = dataSource.entities.getById('Aircraft/Aircraft1');
            // 设置无人机实体的模型
            drone.model = {
              // CesiumDrone.gltf会报错
              // uri:'./assets/SampleData/Models/CesiumDrone.gltf',
        
              uri: './assets/SampleData/Models/Cesium_Air.glb',
              // uri:'./assets/SampleData/Models/ferrari2.gltf',
              // 设置模型最小的时候的像素大小 缩小地球的时候也能看到
              minimumPixelSize: 128,
              // 设置最大规格
              maximumScale: 500,
              // 轮廓的颜色属性
              silhouetteColor: Cesium.Color.WHITE,
              // 指定轮廓的大小
              silhouetteSize: 0
            }
            // 设置无人机的方向 角度
            drone.orientation = new Cesium.VelocityOrientationProperty(drone.position);
            // 设置当前所在的具体的位置
            drone.viewFrom = new Cesium.Cartesian3(0, -30, 30);
            // 设置动起来
            viewer.clock.shouldAnimate = true;
          })
        
  4. 效果:npm run dev 运行

在这里插入图片描述

好博客就要一起分享哦!分享海报

此处可发布评论

评论(0展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695