Browse Source

添加按钮控制图标显隐,回默认视口,控制台风路径隐藏

WQQ 1 tháng trước cách đây
mục cha
commit
6778180927
1 tập tin đã thay đổi với 182 bổ sung24 xóa
  1. 182 24
      WebVue/TaiHufenglang/src/components/TyphoonViewer.vue

+ 182 - 24
WebVue/TaiHufenglang/src/components/TyphoonViewer.vue

@@ -1,5 +1,19 @@
 <template>
   <div id="cesiumContainer" style="height: 100%;width: 100%;"></div>
+
+    <!-- 控制按钮 -->
+    <div class="control-buttons">
+      <button class="control-btn" @click="goToHomeView" title="返回首页视角">
+        <i class="fas fa-home"></i>
+      </button>
+      <button class="control-btn" @click="togglePOIDisplay" title="显示/隐藏POI点">
+        <i class="fas fa-map-marker-alt" :class="{ 'active': poiVisible }"></i>
+      </button>
+      <button class="control-btn" @click="toggleTyphoon" title="显示/隐藏台风并切换视角">
+        <i class="fas fa-wind" :class="{ 'active': typhoonVisible }"></i>
+      </button>
+    </div>
+
   <!-- 自定义弹框组件 -->
   <div v-if="selectedPoint" class="custom-popup" :style="{
     left: `${popupPosition.x}px`,
@@ -39,7 +53,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, onUnmounted } from 'vue'
+import { ref, onMounted, onUnmounted, watch } from 'vue'
 import * as Cesium from 'cesium';
 import "cesium/Build/CesiumUnminified/Widgets/widgets.css";
 import JYLData from '@/assets/Data/THJYL.json'
@@ -52,6 +66,11 @@ const popupPosition = ref({ x: 0, y: 0 });
 let handler = null;
 let viewer = null;
 
+// 控制按钮相关变量
+const poiVisible = ref(true); // POI点显示状态
+const typhoonVisible = ref(true); // 台风显示状态
+const poiEntities = ref([]); // 存储POI实体,用于控制显示隐藏
+
 // 台风相关变量
 const fengquanLayers = ref([]);
 const myEntityCollection = ref(null);
@@ -59,15 +78,103 @@ const tbentity = ref(null);
 const iii = ref(0);
 const currentPointObj = ref(null);
 let typhoonInterval = null;
+// 台风相关实体集合,用于控制显示隐藏
+const typhoonRelatedEntities = ref({
+  paths: [],
+  forecasts: [],
+  warnings: []
+});
 
-// 计算页面缩放比例(与autofit配置一致)
+// 计算页面缩放比例
 const getScaleRatio = () => {
   const designWidth = 1920;
   const designHeight = 1080;
   return Math.min(window.innerWidth / designWidth, window.innerHeight / designHeight);
 };
 
+// 返回首页视角
+const goToHomeView = () => {
+  if (viewer) {
+    viewer.camera.flyTo({
+      destination: Cesium.Cartesian3.fromDegrees(120.169103, 31.226174, 500000),
+      orientation: {
+        heading: Cesium.Math.toRadians(0),
+        pitch: Cesium.Math.toRadians(-90),
+      },
+      duration: 1
+    });
+  }
+};
+
+// 切换POI点显示/隐藏
+const togglePOIDisplay = () => {
+  poiVisible.value = !poiVisible.value;
+  poiEntities.value.forEach(entity => {
+    if (entity && entity.billboard) {
+      entity.billboard.show = poiVisible.value;
+      entity.label.show = poiVisible.value;
+    }
+  });
+};
+
+// 切换台风显示/隐藏并跳转视角
+const toggleTyphoon = () => {
+  typhoonVisible.value = !typhoonVisible.value;
+  
+  // 控制台风相关实体显示/隐藏
+  if (myEntityCollection.value) {
+    myEntityCollection.value.show = typhoonVisible.value;
+  }
+  
+  // 控制风圈显示/隐藏
+  fengquanLayers.value.forEach(entity => {
+    if (entity) {
+      entity.show = typhoonVisible.value;
+    }
+  });
+  
+  // 控制路径线显示/隐藏
+  typhoonRelatedEntities.value.paths.forEach(entity => {
+    if (entity) {
+      entity.show = typhoonVisible.value;
+    }
+  });
+  
+  // 控制预报路径显示/隐藏
+  typhoonRelatedEntities.value.forecasts.forEach(entity => {
+    if (entity) {
+      entity.show = typhoonVisible.value;
+    }
+  });
+  
+  // 控制警戒线显示/隐藏
+  typhoonRelatedEntities.value.warnings.forEach(entity => {
+    if (entity) {
+      entity.show = typhoonVisible.value;
+    }
+  });
+  
+  // 控制台风标记显示/隐藏
+  if (tbentity.value) {
+    tbentity.value.show = typhoonVisible.value;
+  }
+  
+  // 如果显示台风,则跳转到台风视角
+  if (typhoonVisible.value) {
+    viewer.camera.flyTo({
+      destination: Cesium.Cartesian3.fromDegrees(120, 20, 4025692.0),
+    });
+  }
+};
+
+
 onMounted(async () => {
+  // 设置HTML和body样式确保没有边距
+  document.documentElement.style.height = '100%';
+  document.body.style.height = '100%';
+  document.body.style.margin = '0';
+  document.body.style.padding = '0';
+  
   // 初始化Cesium viewer
   viewer = new Cesium.Viewer('cesiumContainer', {
     timeline: false,
@@ -81,47 +188,43 @@ onMounted(async () => {
     vrButton: false,
     selectionIndicator: false,
     infoBox: false,
-    //加载地形效果
+    // 加载地形效果
     terrainProvider: await Cesium.createWorldTerrainAsync({
       requestVertexNormals: true,
-      // requestWaterMask: true,     
     })
   });
 
-  // 多块倾斜摄影瓦片集的URL列表(根据实际路径修改)
+  // 多块倾斜摄影瓦片集的URL列表
   const tilesetUrls = [
     "http://localhost:9003/model/TSQ1234/tileset.json",
     "http://localhost:9003/model/SY123/tileset.json",
   ];
 
-  // 存储加载成功的瓦片集(可选,用于后续管理)
+  // 存储加载成功的瓦片集
   const loadedTilesets = [];
 
-  // 批量加载瓦片集(不调整视角)
+  // 批量加载瓦片集
   async function loadMultipleTilesets() {
     try {
-      // 遍历URL列表,并行加载所有瓦片集
       const promises = tilesetUrls.map(async (url, index) => {
         try {
           const tileset = await Cesium.Cesium3DTileset.fromUrl(url, {
-            maximumScreenSpaceError: 32, // 细节层级控制
+            maximumScreenSpaceError: 32,
             dynamicScreenSpaceError: true,
             skipLevelOfDetail: true,
             maximumConcurrentRequests: 5,
             tileCacheSize: 100
           });
-          // 添加到场景
           viewer.scene.primitives.add(tileset);
           loadedTilesets.push(tileset);
           console.log(`第${index + 1}块瓦片集加载完成`);
           return tileset;
         } catch (error) {
           console.error(`第${index + 1}块瓦片集加载失败:`, error);
-          return null; // 单块失败不影响其他块
+          return null;
         }
       });
 
-      // 等待所有瓦片集加载(无论成功与否)
       await Promise.all(promises);
       console.log("所有瓦片集加载操作已完成");
     } catch (error) {
@@ -129,7 +232,7 @@ onMounted(async () => {
     }
   }
 
-  // 执行加载(加载后保持原有视口)
+  // 执行加载
   loadMultipleTilesets();
 
   // 定义距离显示条件和缩放属性
@@ -142,7 +245,7 @@ onMounted(async () => {
   JYLData.forEach((item) => {
     const position = Cesium.Cartesian3.fromDegrees(
       parseFloat(item.LGTD),
-      parseFloat(item.LTTD)
+      parseFloat(item.LTTD) 
     );
     const entity = viewer.entities.add({
       position: position,
@@ -179,9 +282,10 @@ onMounted(async () => {
       }
     });
     entityDataMap.set(entity.id, item);
+    poiEntities.value.push(entity);
   });
 
-  // 天地图图层
+  // 添加天地图图层
   const tdtLayer = new Cesium.WebMapTileServiceImageryProvider({
     url: `https://t0.tianditu.com/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
     layer: "tdt",
@@ -228,7 +332,7 @@ onMounted(async () => {
 
       if (data) {
         selectedPoint.value = data;
-        // 计算图标屏幕坐标,固定显示在图标上方
+        // 计算图标屏幕坐标
         const entityPosition = viewer.scene.cartesianToCanvasCoordinates(pickedObject.id.position._value);
         if (entityPosition) {
           popupPosition.value = {
@@ -247,6 +351,11 @@ onMounted(async () => {
 
   // 初始化台风相关功能
   initTyphoonVisualization();
+  
+  // 监听窗口大小变化,确保地图铺满
+  window.addEventListener('resize', handleResize);
+  // 初始触发一次 resize 确保地图正确显示
+  handleResize();
 });
 
 // 初始化台风可视化
@@ -348,7 +457,7 @@ const processPoints = (points) => {
   });
   
   // 添加台风路径线
-  viewer.entities.add({
+  const pathEntity = viewer.entities.add({
     polyline: {
       positions: Cesium.Cartesian3.fromDegreesArray(lineArr),
       width: 3,
@@ -356,6 +465,7 @@ const processPoints = (points) => {
       material: Cesium.Color.RED
     }
   });
+  typhoonRelatedEntities.value.paths.push(pathEntity);
   
   if (points.length > 0) {
     // 初始化预报路径
@@ -395,7 +505,7 @@ const initForeast = (data) => {
     });
     
     // 添加预报路径线
-    viewer.entities.add({
+    const forecastEntity = viewer.entities.add({
       polyline: {
         positions: Cesium.Cartesian3.fromDegreesArray(lineArr),
         width: 2,
@@ -405,13 +515,14 @@ const initForeast = (data) => {
         })
       }
     });
+    typhoonRelatedEntities.value.forecasts.push(forecastEntity);
   });
 };
 
 // 初始化警戒线
 const initJJ = () => {
   // 24小时警戒线
-  viewer.entities.add({
+  const line24h = viewer.entities.add({
     name: '24小时警戒线',
     polyline: {
       positions: Cesium.Cartesian3.fromDegreesArray([
@@ -422,9 +533,10 @@ const initJJ = () => {
       clampToGround: true
     }
   });
+  typhoonRelatedEntities.value.warnings.push(line24h);
   
   // 48小时警戒线
-  viewer.entities.add({
+  const line48h = viewer.entities.add({
     name: '48小时警戒线',
     polyline: {
       positions: Cesium.Cartesian3.fromDegreesArray([
@@ -435,9 +547,10 @@ const initJJ = () => {
       clampToGround: true
     }
   });
+  typhoonRelatedEntities.value.warnings.push(line48h);
   
   // 警戒线标签
-  viewer.entities.add({
+  const label24h = viewer.entities.add({
     position: Cesium.Cartesian3.fromDegrees(126.129019, 29.104287),
     label: {
       fillColor: Cesium.Color.RED,
@@ -445,8 +558,9 @@ const initJJ = () => {
       font: '14pt monospace'
     }
   });
+  typhoonRelatedEntities.value.warnings.push(label24h);
   
-  viewer.entities.add({
+  const label48h = viewer.entities.add({
     position: Cesium.Cartesian3.fromDegrees(132, 20),
     label: {
       fillColor: Cesium.Color.YELLOW,
@@ -454,6 +568,7 @@ const initJJ = () => {
       font: '14pt monospace'
     }
   });
+  typhoonRelatedEntities.value.warnings.push(label48h);
 };
 
 // 添加台风动画
@@ -506,7 +621,10 @@ const adds = (data) => {
     
     iii.value = (iii.value + 1) % data.length;
     removeTFLayer();
-    addTyphoonCircle();
+    // 只有当台风可见时才添加风圈
+    if (typhoonVisible.value) {
+      addTyphoonCircle();
+    }
   }, 200);
 };
 
@@ -572,7 +690,7 @@ const removeTFLayer = () => {
 
 // 添加台风风圈
 const addTyphoonCircle = () => {
-  if (!currentPointObj.value) return;
+  if (!currentPointObj.value || !typhoonVisible.value) return;
   
   const circles = ['circle7', 'circle10', 'circle12'];
   circles.forEach(item => {
@@ -653,6 +771,9 @@ onUnmounted(() => {
     clearInterval(typhoonInterval);
   }
   
+  // 移除窗口大小变化监听
+  window.removeEventListener('resize', handleResize);
+  
   // 销毁事件处理器
   if (handler) {
     handler.destroy();
@@ -667,6 +788,43 @@ onUnmounted(() => {
 </script>
 
 <style scoped>
+
+/* 控制按钮样式 */
+.control-buttons {
+  position: absolute;
+  top: 200px;
+  left: 150px;
+  z-index: 100;
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.control-btn {
+  width: 40px;
+  height: 40px;
+  border-radius: 50%;
+  background-color: rgba(255, 255, 255, 0.9);
+  border: none;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  transition: all 0.2s ease;
+  color: #333;
+}
+
+.control-btn:hover {
+  background-color: white;
+  transform: scale(1.1);
+}
+
+.control-btn .active {
+  color: #1E88E5;
+}
+
+
 .custom-popup {
   position: absolute;
   z-index: 1000;