|  | @@ -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;
 |