浏览代码

常规上传

Koishi 7 月之前
父节点
当前提交
c3c67b50a3
共有 2 个文件被更改,包括 616 次插入103 次删除
  1. 1 1
      index.html
  2. 615 102
      src/views/cesium.vue

+ 1 - 1
index.html

@@ -4,7 +4,7 @@
     <meta charset="UTF-8">
     <link rel="icon" href="/favicon.ico">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>Vite App</title>
+    <title>“天镜” 数字孪生可视化引擎</title>
   </head>
   <body>
     <div id="app"></div>

+ 615 - 102
src/views/cesium.vue

@@ -2,27 +2,59 @@
   <div class="mapBox">
     <div id="cesiumContainer" style="width: 100%; height: 100vh"></div>
     <div class="menuBox" :class="allyShow ? '' : 'switch'">
-      <el-button type="primary" @click="resetViewport()">初始化视角</el-button>
-      <el-button
-        :type="windLayer ? 'danger' : 'primary'"
-        @click="switchWindLayer"
-        >{{ windLayer ? "关闭" : "显示" }}风场图</el-button
-      >
-      <el-button
-        :type="cloudLayer ? 'danger' : 'primary'"
-        @click="switchCloudLayer"
-        >{{ cloudLayer ? "关闭" : "显示" }}云图</el-button
-      >
-      <el-button
-        :type="rainLayer ? 'danger' : 'primary'"
-        @click="switchRainLayer"
-        >{{ rainLayer ? "关闭" : "显示" }}降雨图</el-button
-      >
-      <el-button
-        :type="rainLayer ? 'danger' : 'primary'"
-        @click="switchTemperatureLayerr"
-        >{{ rainLayer ? "关闭" : "显示" }}温度图</el-button
-      >
+      <div class="item">
+        <span>图源:</span>
+        <el-select
+          v-model="basicMapId"
+          size="small"
+          style="width: 120px"
+          @change="setMapImageryProvider"
+        >
+          <el-option
+            v-for="item in basicMapList"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          />
+        </el-select>
+      </div>
+      <div class="item">
+        <el-button type="primary" size="small" @click="resetViewport()"
+          >初始化视角</el-button
+        >
+      </div>
+      <div class="item">
+        <el-button
+          size="small"
+          :type="windLayer ? 'danger' : 'primary'"
+          @click="switchWindLayer"
+          >{{ windLayer ? "关闭" : "显示" }}风场图</el-button
+        >
+      </div>
+      <div class="item">
+        <el-button
+          size="small"
+          :type="cloudLayer ? 'danger' : 'primary'"
+          @click="switchCloudLayer"
+          >{{ cloudLayer ? "关闭" : "显示" }}云图</el-button
+        >
+      </div>
+      <div class="item">
+        <el-button
+          size="small"
+          :type="rainLayer ? 'danger' : 'primary'"
+          @click="switchRainLayer"
+          >{{ rainLayer ? "关闭" : "显示" }}降雨图</el-button
+        >
+      </div>
+      <div class="item">
+        <el-button
+          size="small"
+          :type="rainLayer ? 'danger' : 'primary'"
+          @click="switchTemperatureLayerr"
+          >{{ rainLayer ? "关闭" : "显示" }}温度图</el-button
+        >
+      </div>
       <el-tooltip
         class="box-item"
         effect="dark"
@@ -43,14 +75,52 @@
         </el-icon>
       </el-tooltip>
     </div>
+    <div
+      class="tag"
+      :style="`left:${userClickLeft}px;top:${userClickTop}px`"
+      v-if="tagMsg || tagMsg === ''"
+    >
+      <el-icon class="is-loading" v-if="tagMsg === ''">
+        <Loading />
+      </el-icon>
+      <span v-else>{{ tagMsg || "" }}</span>
+    </div>
+    <div class="devInfoBox" v-if="showDevInfoBox">
+      <div class="item">===&nbsp;帧率与内存&nbsp;===</div>
+      <div class="item">运行帧率:&nbsp;{{ fps }}</div>
+      <div class="item">响应时长:&nbsp;{{ ms }}</div>
+      <div class="item">内存占用:&nbsp;{{ jsHeapSize }}</div>
+      <template v-if="gVendor || gRenderer">
+        <div class="item" style="margin-top: 12px">
+          ====&nbsp;显卡信息&nbsp;====
+        </div>
+        <el-tooltip
+          effect="dark"
+          :content="gVendor"
+          placement="top-end"
+          v-if="gVendor"
+        >
+          <div class="item">制造商:&nbsp;{{ gVendor }}</div>
+        </el-tooltip>
+        <el-tooltip
+          effect="dark"
+          :content="gRenderer"
+          placement="top-end"
+          v-if="gRenderer"
+        >
+          <div class="item">型号:&nbsp;{{ gRenderer }}</div>
+        </el-tooltip>
+      </template>
+    </div>
   </div>
 </template>
 
 <script>
-import * as Cesium from "../Cesium";
-import "../Cesium/Widgets/widgets.css";
+// import * as Cesium from "../Cesium";
+// import "../Cesium/Widgets/widgets.css";
+import * as Cesium from "cesium";
+import "cesium/Build/Cesium/Widgets/widgets.css";
 import Windy from "../assets/wind/Windy_source.js";
-import SingleImageProvider from "../assets/wind/SingleImageProvider";
 
 import basicGeoJson from "../assets/geoJson/basic.json";
 import windLineJson from "../assets/geoJson/windLine_2017121300.json";
@@ -58,19 +128,62 @@ import windLineJson from "../assets/geoJson/windLine_2017121300.json";
 import axios from "axios";
 export default {
   name: "CesiumMap",
+
   data() {
     return {
+      checkMode: false, // 调试模式
       allyShow: false,
       viewer: null,
       windLayer: null, // 风场图
       windLayerTimmer: null, // 风场图计时器
       cloudLayer: null, // 卫星云图
-      rainLayer: null, //
+      rainLayer: null, // 降雨图
+      basicMapId: "gaodeyingxiang", // 地球底图 ID
+      // 地球底图数组
+      basicMapList: [
+        {
+          id: "gaodeyingxiang",
+          name: "高德影像地图",
+          url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
+          minimumLevel: 3,
+          maximumLevel: 18,
+          credit: "basicMap",
+        },
+        {
+          id: "gaodeshiliang",
+          name: "高德矢量地图",
+          url: "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
+          minimumLevel: 3,
+          maximumLevel: 18,
+          credit: "basicMap",
+        },
+        {
+          id: "carto",
+          name: "Carto地图",
+          url: "http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
+          credit: "basicMap",
+        },
+      ],
+      earthLayer: [],
+      userClickLeft: 0,
+      userClickTop: 0,
+      tagMsg: null,
+      systemInfoTimmer: null,
+      showDevInfoBox: true,
+      fps: "", // 设备帧率
+      ms: "", // 设备响应时间
+      jsHeapSize: "", // 内存占用
+      gVendor: "",
+      gRenderer: "",
     };
   },
 
   mounted() {
+    this.initEventListener();
     this.initCesium();
+    if (this.showDevInfoBox) {
+      this.initSystemInfo();
+    }
   },
 
   unmounted() {
@@ -78,45 +191,66 @@ export default {
       clearInterval(this.windLayerTimmer);
       this.windLayer.removeLines();
       this.windLayer = null;
+      this.windLayerTimmer = null;
     }
+
+    clearInterval(this.systemInfoTimmer);
+    this.systemInfoTimmer = null;
   },
 
   methods: {
-    initCesium() {
+    // 初始化一些监听事件
+    initEventListener() {
+      const mapBox = document.querySelector(".mapBox");
+      mapBox.addEventListener("click", (e) => {
+        const rect = mapBox.getBoundingClientRect();
+        this.userClickLeft = (e.clientX - rect.left).toFixed(0);
+        this.userClickTop = (e.clientY - rect.top + 20).toFixed(0);
+      });
+    },
+
+    // 初始化地球
+    async initCesium() {
       // 需要从 https://cesium.com/ion/signup 获取
       Cesium.Ion.defaultAccessToken =
         "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIwYTQwNDk3MC05YTZkLTQ2ZTEtODc0MS1lZTFkYjFlOTFmNmQiLCJpZCI6MTcyNDQ1LCJpYXQiOjE3NTQ4ODA4MzF9.KnhENYiHxNwTkhTWRA-lHqG59coLVT2FsIyOru2TV3E";
+
+      // 修改 Cesium 默认地图视角为宁夏,狗东西没效果不知道为什么
+      // Cesium.Camera.DEFAULT_VIEW_RACTANGLE = Cesium.Rectangle.fromDegrees(
+      //   104.17,
+      //   35.14,
+      //   107.72,
+      //   39.23
+      // );
+
       const viewer = new Cesium.Viewer("cesiumContainer", {
-        baseLayerPicker: false,
-        animation: false,
+        geocoder: false, // 地址搜索控件
+        homeButton: false, // 返回地图初始位置控件
+        infoBox: false, // 地图默认的信息控件
+        sceneModePicker: false, // 场景模式切换控件
+        baseLayerPicker: false, // 底图切换控件
+        navigationHelpButton: false, // 帮助控件
+        animation: false, // 动画控制控件
+        timeline: false, // 时间线控件
+        fullscreenButton: false, // 全屏按钮控件
+        imageryProvider: false, // 是否显示 Cesium 默认地图的底图
         vrButton: false,
-        geocoder: false,
-        homeButton: false,
-        infoBox: false,
-        sceneModePicker: false,
         selectionIndicator: false,
-        timeline: false,
-        fullscreenButton: false,
-        navigationHelpButton: false,
         shouldAnimate: true,
+        // terrainProvider: await Cesium.createWorldTerrainAsync({
+        //   requestVertexNormals: true,
+        //   requestWaterMask: true,
+        // }),
+        // terrainProvider: new Cesium.CesiumTerrainProvider({
+        //   url: "/static/layer.json", // 对应 public/terrain-data 目录
+        //   requestVertexNormals: true, // 保留法线数据(光照效果)
+        //   requestWaterMask: false, // 本地地形通常无水面效果(需自定义)
+        // }),
       });
 
-      // 隐藏logo
-      // this.$nextTick(() => {
-      //   document.querySelector(".cesium-viewer-bottom")?.remove();
-      // });
-
-      // 隐藏logo
+      // 隐藏 Cesium Logo
       viewer.cesiumWidget.creditContainer.style.display = "none";
 
-      // 添加中文底图
-      const imageryProvider = new Cesium.UrlTemplateImageryProvider({
-        url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
-        credit: "高德地图",
-      });
-
-      viewer.imageryLayers.addImageryProvider(imageryProvider);
-
       // 添加一些3D模型
       //   const addModel = (name, lon, lat, height) => {
       //     viewer.entities.add({
@@ -134,48 +268,357 @@ export default {
 
       // 添加点击事件显示坐标
       viewer.screenSpaceEventHandler.setInputAction((movement) => {
-        const cartesian = viewer.camera.pickEllipsoid(
-          movement.position,
-          viewer.scene.globe.ellipsoid
-        );
-        if (cartesian) {
-          const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
-          const lon = Cesium.Math.toDegrees(cartographic.longitude).toFixed(5);
-          const lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(5);
-
-          viewer.entities.removeAll();
-          viewer.entities.add({
-            position: cartesian,
-            point: {
-              pixelSize: 10,
-              color: Cesium.Color.RED,
-            },
-            label: {
-              text: `经度: ${lon}°, 纬度: ${lat}°`,
-              font: '16px "Microsoft YaHei"',
-              fillColor: Cesium.Color.WHITE,
-              outlineColor: Cesium.Color.BLACK,
-              outlineWidth: 2,
-              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
-              pixelOffset: new Cesium.Cartesian2(0, -30),
+        try {
+          const ray = viewer.camera.getPickRay(movement.position);
+          if (!ray) {
+            this.tagMsg = null;
+            console.log("无法获取射线");
+            return;
+          }
+
+          const position = viewer.scene.globe.pick(ray, viewer.scene);
+          if (!position) {
+            this.tagMsg = null;
+            console.log("未找到地球表面交点");
+            return;
+          }
+
+          const cartographic = Cesium.Cartographic.fromCartesian(position);
+          if (!cartographic) {
+            this.tagMsg = null;
+            console.log("坐标转换失败");
+            return;
+          }
+
+          const level = this.calculateTileLevel(viewer);
+          const tilingScheme = new Cesium.WebMercatorTilingScheme();
+
+          // 确保tilingScheme有positionToTileXY方法
+          if (!tilingScheme.positionToTileXY) {
+            console.error("tilingScheme没有positionToTileXY方法");
+            return;
+          }
+
+          if (!this.cloudLayer) {
+            this.tagMsg = null;
+          } else {
+            this.tagMsg = "";
+          }
+
+          const tileXY = tilingScheme.positionToTileXY(cartographic, level);
+
+          this.checkMode &&
+            console.log(
+              `瓦片坐标: 级别=${level}, X=${tileXY.x}, Y=${tileXY.y}`
+            );
+
+          // const mapSelect = this.basicMapList.find((ele) => {
+          //   return ele.id === this.basicMapId;
+          // });
+
+          const clickTileUrl = this.replaceTemplate(
+            // mapSelect.url,
+            "https://tile.openweathermap.org/map/clouds_new/{z}/{x}/{y}.png?appid=3b66d35579770393051599f8d518df4a",
+            level,
+            tileXY
+          );
+
+          this.checkMode && console.log(`用户点击位置瓦片url: ${clickTileUrl}`);
+
+          // 存储当前瓦片信息
+          const layer = viewer.imageryLayers.get(0);
+          const provider = layer.imageryProvider;
+          const currentTile = {
+            x: tileXY.x,
+            y: tileXY.y,
+            level: level,
+            rectangle: tilingScheme.tileXYToRectangle(
+              tileXY.x,
+              tileXY.y,
+              level
+            ),
+            size: {
+              width: provider.tileWidth || 256,
+              height: provider.tileHeight || 256,
             },
-          });
+          };
+
+          // 计算并显示在瓦片内的位置
+          const clickPos = this.calculateTilePosition(
+            cartographic,
+            currentTile
+          );
+
+          if (this.cloudLayer) {
+            this.getTileImageOpacity(
+              clickTileUrl,
+              clickPos.pixelX,
+              clickPos.pixelY
+            ).then((imgSource) => {
+              const {
+                rawAlpha, // 原始透明度值 (0-255)
+                alphaPercentage, // 透明度百分比
+                whiteScore, // 白色程度得分 (0-100)
+              } = imgSource;
+              this.checkMode && console.log(111, alphaPercentage);
+              this.tagMsg = `${alphaPercentage * 2}%`;
+            });
+          }
+
+          if (this.checkMode) {
+            const tileRectangle = tilingScheme.tileXYToRectangle(
+              tileXY.x,
+              tileXY.y,
+              level
+            );
+            this.highlightTile(viewer, tileRectangle);
+          }
+        } catch (error) {
+          console.error("获取瓦片时出错:", error);
         }
+
+        return;
+
+        // const cartesian = viewer.camera.pickEllipsoid(
+        //   movement.position,
+        //   viewer.scene.globe.ellipsoid
+        // );
+        // if (cartesian) {
+        //   const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
+        //   const lon = Cesium.Math.toDegrees(cartographic.longitude).toFixed(5);
+        //   const lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(5);
+
+        //   viewer.entities.removeAll();
+        //   viewer.entities.add({
+        //     position: cartesian,
+        //     point: {
+        //       pixelSize: 10,
+        //       color: Cesium.Color.RED,
+        //     },
+        //     label: {
+        //       text: `经度: ${lon}°, 纬度: ${lat}°`,
+        //       font: '16px "Microsoft YaHei"',
+        //       fillColor: Cesium.Color.WHITE,
+        //       outlineColor: Cesium.Color.BLACK,
+        //       outlineWidth: 2,
+        //       style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+        //       pixelOffset: new Cesium.Cartesian2(0, -30),
+        //     },
+        //   });
+        // }
       }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
 
+      // 监听鼠标滚轮事件
+      viewer.screenSpaceEventHandler.setInputAction((wheelment) => {
+        this.tagMsg = null;
+        //从Cesium中获取当前地图瓦片等级
+        // let tiles = new Set();
+        // let tilesToRender = viewer.scene.globe._surface._tilesToRender;
+        // if (Cesium.defined(tilesToRender)) {
+        //   for (let i = 0; i < tilesToRender.length; i++) {
+        //     tiles.add(tilesToRender[i].level);
+        //   }
+        //   console.log("当前地图瓦片级别为:");
+        //   console.log(tiles);
+        // }
+      }, Cesium.ScreenSpaceEventType.WHEEL);
+
       this.viewer = viewer;
 
+      this.setMapImageryProvider();
       this.initGeoJsonData();
     },
 
+    // 初始化性能监控
+    initSystemInfo() {
+      this.viewer.scene.debugShowFramesPerSecond = false;
+
+      // 性能监控变量
+      let lastFrameTime = performance.now();
+      let frameCount = 0;
+      let fps = 0;
+      let frameTime = 0;
+
+      // 获取帧率与响应时长
+      this.viewer.scene.postRender.addEventListener(() => {
+        const now = performance.now();
+        const delta = now - lastFrameTime;
+
+        frameCount++;
+
+        // 每秒更新一次数据(避免更新太频繁)
+        if (delta >= 1000) {
+          fps = Math.round((frameCount * 1000) / delta);
+          frameTime = delta / frameCount;
+
+          // 更新显示
+          this.fps = `${fps} FPS`;
+          this.ms = `${frameTime.toFixed(1) + " ms"}`;
+
+          // 重置计数器
+          frameCount = 0;
+          lastFrameTime = now;
+        }
+      });
+
+      // 获取内存占用
+      if (window.performance && performance.memory) {
+        const jsHeapSize = performance.memory.usedJSHeapSize / 1048576;
+        this.jsHeapSize = `${parseInt(jsHeapSize)} MB`;
+        // const memory = performance.memory;
+        // console.log("已分配堆内存:", memory.totalJSHeapSize / 1048576 + " MB");
+        // console.log("已使用堆内存:", memory.usedJSHeapSize / 1048576 + " MB");
+        // console.log("堆内存限制:", memory.jsHeapSizeLimit / 1048576 + " MB");
+      }
+
+      // 获取显卡信息
+      const canvas = document.createElement("canvas");
+      const gl = canvas.getContext("webgl");
+      if (gl) {
+        const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
+        if (debugInfo) {
+          const gVendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
+          const gRenderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
+
+          // console.log("GPU厂商:", gVendor);
+          // console.log("GPU型号:", gRenderer);
+
+          this.gVendor = gVendor;
+          this.gRenderer = gRenderer.split(",")?.[1]
+            ? gRenderer.split(",")?.[1]
+            : "";
+        }
+      }
+    },
+
+    // 计算瓦片级别的辅助函数
+    calculateTileLevel(viewer) {
+      // 方法1:根据相机高度估算
+      const height = viewer.camera.positionCartographic.height;
+      if (!height) return 12; // 默认值
+
+      // 高度与级别的近似关系(根据实际需求调整)
+      const level = Math.floor(20 - Math.log(height / 1000) / Math.log(2));
+      return Math.max(0, Math.min(18, level)); // 限制在0-18级之间
+
+      // 方法2:使用当前视图的细节层次
+      // return viewer.scene.globe.maximumScreenSpaceError;
+    },
+
+    // 高亮显示瓦片的辅助函数
+    highlightTile(viewer, rectangle) {
+      // 移除之前的高亮
+      viewer.entities.removeById("highlighted-tile");
+
+      // 添加新的高亮
+      viewer.entities.add({
+        id: "highlighted-tile",
+        rectangle: {
+          coordinates: rectangle,
+          material: Cesium.Color.RED.withAlpha(0.3),
+          outline: true,
+          outlineColor: Cesium.Color.RED,
+          outlineWidth: 2,
+        },
+      });
+    },
+
+    // 计算在瓦片内的位置
+    calculateTilePosition(cartographic, tile) {
+      const rect = tile.rectangle;
+      const size = tile.size;
+
+      // 计算在瓦片内的归一化位置
+      const lonNormalized =
+        (cartographic.longitude - rect.west) / (rect.east - rect.west);
+      const latNormalized =
+        (cartographic.latitude - rect.south) / (rect.north - rect.south);
+
+      // 转换为像素坐标(原点在左上角)
+      const pixelX = Math.floor(lonNormalized * size.width);
+      const pixelY = Math.floor((1 - latNormalized) * size.height); // 翻转Y轴
+
+      this.checkMode && console.log(`left:${pixelX},top:${pixelY}`);
+      return { pixelX, pixelY };
+    },
+
+    // canvas 获取地图瓦片颜色信息
+    async getTileImageOpacity(imageUrl, left, top) {
+      // 1. 创建临时图像加载网络图片
+      const img = new Image();
+      img.crossOrigin = "Anonymous"; // 解决跨域问题
+      img.src = imageUrl;
+
+      // 2. 图片加载完成后处理
+      await new Promise((resolve) => (img.onload = resolve));
+
+      // 3. 创建Canvas并绘制图像
+      const canvas = document.createElement("canvas");
+      canvas.width = img.width;
+      canvas.height = img.height;
+      const ctx = canvas.getContext("2d");
+      ctx.drawImage(img, 0, 0);
+
+      // 4. 获取鼠标点击位置的像素数据
+      const pixelData = ctx.getImageData(left, top, 1, 1).data;
+      const [r, g, b, alpha] = pixelData;
+
+      // 5. 计算白色程度(RGB接近255的程度)
+      const whiteRatio = (r + g + b) / (3 * 255); // RGB平均值归一化
+      const whiteScore = Math.round(whiteRatio * 100); // 映射到0-100
+
+      // 6. 返回结果
+      return {
+        rawAlpha: alpha, // 原始透明度值 (0-255)
+        alphaPercentage: Math.round((alpha / 255) * 100), // 透明度百分比
+        whiteScore: whiteScore, // 白色程度得分 (0-100)
+      };
+    },
+
+    // 替换底图 xyz 值为鼠标点击位置的值并返回
+    replaceTemplate(str, level, tileXY) {
+      return str.replace(/\{([xyz])\}/g, (match, key) => {
+        switch (key) {
+          case "x":
+            return tileXY.x;
+          case "y":
+            return tileXY.y;
+          case "z":
+            return level;
+          default:
+            return match; // 未匹配时返回原内容(理论上不会执行)
+        }
+      });
+    },
+
+    // 设置地球底图
+    setMapImageryProvider() {
+      if (this.imageryProvider) {
+        this.viewer.imageryLayers.remove(this.imageryProvider);
+        this.imageryProvider = null;
+      }
+
+      const imageryProvider = this.basicMapList.find((ele) => {
+        return ele.id === this.basicMapId;
+      });
+
+      this.imageryProvider = new Cesium.UrlTemplateImageryProvider(
+        imageryProvider
+      );
+
+      // 添加底图
+      this.viewer.imageryLayers.addImageryProvider(this.imageryProvider);
+    },
+
     // 初始化 geoJson 数据
     async initGeoJsonData() {
       // 创建GeoJSON数据源
       await new Cesium.GeoJsonDataSource.load(basicGeoJson, {
         stroke: Cesium.Color.WHITE, // 边界线颜色
-        fill: Cesium.Color.BLACK.withAlpha(0.1), // 填充颜色
+        fill: Cesium.Color.BLACK.withAlpha(0), // 填充颜色
         strokeWidth: 1, // 边界线宽度
         markerSymbol: "?", // 点要素的符号
+        clampToGround: true, // 贴地
       }).then((dataSource) => {
         // 添加到视图
         this.viewer.dataSources.add(dataSource);
@@ -183,9 +626,7 @@ export default {
         for (let i = 0; i < entities.length; i++) {
           let entity = entities[i];
 
-          let polyPositions = entity.polygon.hierarchy.getValue(
-            Cesium.JulianDate.now()
-          ).positions;
+          entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;
           //单独设置线条样式
           var positions = entity.polygon.hierarchy._value.positions;
 
@@ -211,9 +652,10 @@ export default {
 
         cities.forEach((city) => {
           labelLayer.add({
-            position: Cesium.Cartesian3.fromDegrees(city.lon, city.lat),
+            name: "cityLabel",
+            position: Cesium.Cartesian3.fromDegrees(city.lon, city.lat, 10),
             text: city.name,
-            font: 'bold 16px "Microsoft YaHei", sans-serif',
+            font: 'bold 14px "Microsoft YaHei", sans-serif',
             fillColor: Cesium.Color.YELLOW,
             outlineColor: Cesium.Color.BLACK,
             outlineWidth: 2,
@@ -268,6 +710,20 @@ export default {
       };
     },
 
+    // 获取当前地图瓦片级别(暂时没用到怀疑有BUG)
+    getTileLevel() {
+      let tiles = new Set();
+      let tilesToRender = this.viewer.scene.globe._surface._tilesToRender;
+      if (Cesium.defined(tilesToRender)) {
+        for (let i = 0; i < tilesToRender.length; i++) {
+          tiles.add(tilesToRender[i].level);
+        }
+        return [...tiles].sort((a, b) => {
+          return b - a;
+        })[0];
+      }
+    },
+
     // 显示云图
     showCloudLayer() {
       // 设置云图位置(示例:覆盖中国区域)
@@ -278,23 +734,31 @@ export default {
       //   53.55 // 北纬
       // );
 
-      const now = new Date();
-      const year = now.getFullYear();
-      const month = String(now.getMonth() + 1).padStart(2, "0");
-      const day = String(now.getDate()).padStart(2, "0");
-      const hour = String(Math.floor(now.getHours() / 3) * 3).padStart(2, "0"); // 每3小时更新
+      // const now = new Date();
+      // const year = now.getFullYear();
+      // const month = String(now.getMonth() + 1).padStart(2, "0");
+      // const day = String(now.getDate()).padStart(2, "0");
+      // const hour = String(Math.floor(now.getHours() / 3) * 3).padStart(2, "0"); // 每3小时更新
+
+      // // 创建云图图层
+      // const cloudLayer = this.viewer.imageryLayers.addImageryProvider(
+      //   new Cesium.UrlTemplateImageryProvider({
+      //     url: `https://data.ventusky.com/${year}/${month}/${day}/icon/whole_world/hour_${hour}/icon_oblacnost_${year}${month}${day}_${hour}.jpg`,
+      //     rectangle: Cesium.Rectangle.fromDegrees(-180, -90, 180, 90),
+      //     credit: "实时卫星云图",
+      //   })
+      // );
 
-      // 创建云图图层
+      // 调用云层底图
       const cloudLayer = this.viewer.imageryLayers.addImageryProvider(
         new Cesium.UrlTemplateImageryProvider({
-          url: `https://data.ventusky.com/${year}/${month}/${day}/icon/whole_world/hour_${hour}/icon_oblacnost_${year}${month}${day}_${hour}.jpg`,
-          rectangle: Cesium.Rectangle.fromDegrees(-180, -90, 180, 90),
-          credit: "实时卫星云图",
+          url: "https://tile.openweathermap.org/map/clouds_new/{z}/{x}/{y}.png?appid=3b66d35579770393051599f8d518df4a",
+          credit: "云层影像地图",
         })
       );
 
       // 设置蓝色调效果
-      cloudLayer.alpha = 0.75; // 透明度
+      cloudLayer.alpha = 1; // 透明度
       cloudLayer.brightness = 1; // 亮度
       cloudLayer.contrast = 1; // 对比度
 
@@ -314,6 +778,7 @@ export default {
     // 移除卫星云图
     removeCloudLayer() {
       if (this.cloudLayer) {
+        this.tagMsg = null;
         this.viewer.imageryLayers.remove(this.cloudLayer);
         this.cloudLayer = null;
       }
@@ -328,25 +793,24 @@ export default {
       }
     },
 
-    // 切换微星图显隐
-    // switchCloudLayer() {
-    //   if (this.cloudLayer) {
-    //     this.removeCloudLayer();
-    //   } else {
-    //     this.showCloudLayer();
-    //   }
-    // },
-
+    // 切换卫星云图显隐
     switchCloudLayer() {
-      this.$router.push({
-        path: "/cloudLayer",
-      });
+      // this.$router.push({
+      //   path: "/cloudLayer",
+      // });
+      if (this.cloudLayer) {
+        this.removeCloudLayer();
+      } else {
+        this.showCloudLayer();
+      }
     },
+
     switchRainLayer() {
       this.$router.push({
         path: "/rainLayer",
       });
     },
+
     switchTemperatureLayerr() {
       this.$router.push({
         path: "/temperatureLayer",
@@ -362,6 +826,7 @@ export default {
   height: 100%;
   position: relative;
   box-sizing: content-box;
+  position: relative;
 
   .menuBox {
     position: absolute;
@@ -374,6 +839,15 @@ export default {
     align-items: center;
     padding: 10px;
 
+    .el-button {
+      margin: 0;
+    }
+
+    .item {
+      font-size: 12px;
+      margin-left: 10px;
+    }
+
     &.switch {
       opacity: 0;
       transition: 0.2s;
@@ -384,5 +858,44 @@ export default {
       }
     }
   }
+
+  .tag {
+    position: absolute;
+    left: 0;
+    top: 0;
+    background: #fff;
+    font-size: 12px;
+    color: #000;
+    padding: 4px 8px;
+    border-radius: 28px;
+    transform: translate(-50%, -50%);
+    transition: 0.1s;
+    pointer-events: none;
+  }
+
+  .devInfoBox {
+    width: 130px;
+    position: absolute;
+    right: 0;
+    bottom: 0;
+    padding: 4px;
+    font-size: 12px;
+    color: #fff;
+    background: rgba(0, 0, 0, 0.25);
+    display: flex;
+    flex-direction: column;
+    justify-content: flex-start;
+    align-items: flex-start;
+    z-index: 500;
+    user-select: none;
+
+    .item {
+      width: 100%;
+      margin-top: 4px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+    }
+  }
 }
 </style>