在vite创建的vue3项目中使用Cesium标记地点(基于加载建筑样式,划分区域)

在vite创建的vue3项目中使用Cesium标记地点(基于加载建筑样式,划分区域)

  • 用到的文件 提取码:99jq
  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()));
              // 这地方的cartographicPosition.longitude,我当时报错了,我是直接敲完cartographicPosition之后,把前边的let longtitide中的longtitude直接复制过来的,这好像不行,就老老实实的敲上就行,或者敲完lon,出来提示之后选longtitude。
              let latitude = Cesium.Math.toDegrees(cartographicPosition.latitude);
              let longtitude = Cesium.Math.toDegrees(cartographicPosition.longitude);
              // 修改描述
              let description = ''+''+''+''+''+'
      ' + "longtitude" + '' + longtitude.toFixed(5) + '
      ' + "latitude" + '' + latitude.toFixed(5) + '
      ' + "实时人流" + '' + Math.floor(Math.random() * 20000) + '
      ' + "安全等级" + '' + Math.floor(Math.random() * 5) + '
      '; entity.description = description;}}})})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 = '
    3. ' + '' + '' + '' + '' + '
      ' + "longtitude" + '' + longtitude.toFixed(5) + '
      ' + "latitude" + '' + latitude.toFixed(5) + '
      ' + "实时人流" + '' + Math.floor(Math.random() * 20000) + '
      ' + "安全等级" + '' + Math.floor(Math.random() * 5) + '
      '; entity.description = description; } } })
    4. 效果:npm run dev 运行

    5. 你可能感兴趣的:(Cesium学习,Cesium,vue)