|  | @@ -1,5 +1,18 @@
 | 
	
		
			
				|  |  |  <template>
 | 
	
		
			
				|  |  |    <div id="cesiumContainer" style="height: 100%;width: 100%;"></div>
 | 
	
		
			
				|  |  | +  <!-- 自定义弹框组件 -->
 | 
	
		
			
				|  |  | +  <div v-if="selectedPoint" class="custom-popup" :style="{
 | 
	
		
			
				|  |  | +    left: `${popupPosition.x}px`,
 | 
	
		
			
				|  |  | +    top: `${popupPosition.y}px`,
 | 
	
		
			
				|  |  | +    display: selectedPoint ? 'block' : 'none'
 | 
	
		
			
				|  |  | +  }">
 | 
	
		
			
				|  |  | +    <div class="popup-content">
 | 
	
		
			
				|  |  | +      <h3>{{ selectedPoint.STNM || '未知点' }}</h3>
 | 
	
		
			
				|  |  | +      <p><strong>经度:</strong> {{ selectedPoint.LGTD }}</p>
 | 
	
		
			
				|  |  | +      <p><strong>纬度:</strong> {{ selectedPoint.LTTD }}</p>
 | 
	
		
			
				|  |  | +      <div class="popup-arrow"></div>
 | 
	
		
			
				|  |  | +    </div>
 | 
	
		
			
				|  |  | +  </div>
 | 
	
		
			
				|  |  |  </template>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  <script setup>
 | 
	
	
		
			
				|  | @@ -7,9 +20,11 @@ import { ref, onMounted, onUnmounted, getCurrentInstance } from 'vue'
 | 
	
		
			
				|  |  |  import * as Cesium from 'cesium';
 | 
	
		
			
				|  |  |  import "cesium/Build/CesiumUnminified/Widgets/widgets.css";
 | 
	
		
			
				|  |  |  import JYLData from '@/assets/Data/THJYL.json'
 | 
	
		
			
				|  |  | -import { color } from 'echarts';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  const TDTTK = "d9e7aa2ad204aba6aeedea6f5ab48ed9";
 | 
	
		
			
				|  |  | +const selectedPoint = ref(null);
 | 
	
		
			
				|  |  | +const popupPosition = ref({ x: 0, y: 0 });
 | 
	
		
			
				|  |  | +let handler = null;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  onMounted(() => {
 | 
	
		
			
				|  |  |    const viewer = new Cesium.Viewer('cesiumContainer', {
 | 
	
	
		
			
				|  | @@ -26,28 +41,25 @@ onMounted(() => {
 | 
	
		
			
				|  |  |      infoBox: false,
 | 
	
		
			
				|  |  |    });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // 定义距离显示条件和缩放属性
 | 
	
		
			
				|  |  | +  // 定义距离显示条件和缩放属性
 | 
	
		
			
				|  |  |    const distanceDisplayCondition = new Cesium.DistanceDisplayCondition(
 | 
	
		
			
				|  |  |      0,  // 最小显示距离(0表示始终显示)
 | 
	
		
			
				|  |  |      10000000  // 最大显示距离(1000公里外不显示)
 | 
	
		
			
				|  |  |    );
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    const pointNearFarScalar = new Cesium.NearFarScalar(
 | 
	
		
			
				|  |  |      10000, 1.0,     // 近点距离和缩放比例
 | 
	
		
			
				|  |  |      1000000, 0.3    // 远点距离和缩放比例
 | 
	
		
			
				|  |  |    );
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    const labelNearFarScalar = new Cesium.NearFarScalar(
 | 
	
		
			
				|  |  |      10000, 1.0,     // 近点距离和缩放比例
 | 
	
		
			
				|  |  |      400000, 0     // 远点距离和缩放比例(50公里外完全隐藏)
 | 
	
		
			
				|  |  |    );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  //   const entitiesNearFarScalar = new Cesium.NearFarScalar(
 | 
	
		
			
				|  |  | -  //   10000, 1.0,     // 近点距离和缩放比例
 | 
	
		
			
				|  |  | -  //   1000000, 0.1     // 远点距离和缩放比例(50公里外完全隐藏)
 | 
	
		
			
				|  |  | -  // );
 | 
	
		
			
				|  |  | +  // 存储实体与数据的映射
 | 
	
		
			
				|  |  | +  const entityDataMap = new Map();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  |    // 遍历数据并添加点和标签
 | 
	
		
			
				|  |  |    JYLData.forEach((item) => {
 | 
	
		
			
				|  |  |      const position = Cesium.Cartesian3.fromDegrees(
 | 
	
	
		
			
				|  | @@ -56,9 +68,8 @@ onMounted(() => {
 | 
	
		
			
				|  |  |      );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // 创建组合了图标和标签的实体
 | 
	
		
			
				|  |  | -    viewer.entities.add({
 | 
	
		
			
				|  |  | +    const entity = viewer.entities.add({
 | 
	
		
			
				|  |  |        position: position,
 | 
	
		
			
				|  |  | -      // scaleByDistance:entitiesNearFarScalar,
 | 
	
		
			
				|  |  |        billboard: {
 | 
	
		
			
				|  |  |          image: '/src/assets/icon/blue.png',  // 图标路径
 | 
	
		
			
				|  |  |          scale: 0.4,
 | 
	
	
		
			
				|  | @@ -86,32 +97,40 @@ onMounted(() => {
 | 
	
		
			
				|  |  |          distanceDisplayCondition: distanceDisplayCondition,
 | 
	
		
			
				|  |  |          scaleByDistance: labelNearFarScalar
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  | +      // 添加一个唯一ID用于识别
 | 
	
		
			
				|  |  | +      id: `point-${item.STCD || item.LGTD + '-' + item.LTTD}`,
 | 
	
		
			
				|  |  | +      properties: {
 | 
	
		
			
				|  |  | +        data: item  // 直接将数据附加到实体属性
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // 天地图影像
 | 
	
		
			
				|  |  | -  const tdtLayer = new Cesium.WebMapTileServiceImageryProvider({
 | 
	
		
			
				|  |  | -    url: `http://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",
 | 
	
		
			
				|  |  | -    style: "default",
 | 
	
		
			
				|  |  | -    format: "image/jpeg",
 | 
	
		
			
				|  |  | -    tileMatrixSetID: "w",
 | 
	
		
			
				|  |  | -    maximumLevel: 18,
 | 
	
		
			
				|  |  | -    show: false,
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  viewer.imageryLayers.addImageryProvider(tdtLayer);
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -  // 天地图注记
 | 
	
		
			
				|  |  | -  const tdtAnnotionLayer = new Cesium.WebMapTileServiceImageryProvider({
 | 
	
		
			
				|  |  | -    url: `http://t0.tianditu.com/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
 | 
	
		
			
				|  |  | -    layer: "tdtAnno",
 | 
	
		
			
				|  |  | -    style: "default",
 | 
	
		
			
				|  |  | -    format: "image/jpeg",
 | 
	
		
			
				|  |  | -    tileMatrixSetID: "w",
 | 
	
		
			
				|  |  | -    maximumLevel: 18,
 | 
	
		
			
				|  |  | -    show: false,
 | 
	
		
			
				|  |  | +    // 存储实体与数据的映射关系
 | 
	
		
			
				|  |  | +    entityDataMap.set(entity.id, item);
 | 
	
		
			
				|  |  |    });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  // // 天地图影像
 | 
	
		
			
				|  |  | +  // const tdtLayer = new Cesium.WebMapTileServiceImageryProvider({
 | 
	
		
			
				|  |  | +  //   url: `http://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",
 | 
	
		
			
				|  |  | +  //   style: "default",
 | 
	
		
			
				|  |  | +  //   format: "image/jpeg",
 | 
	
		
			
				|  |  | +  //   tileMatrixSetID: "w",
 | 
	
		
			
				|  |  | +  //   maximumLevel: 18,
 | 
	
		
			
				|  |  | +  //   show: false,
 | 
	
		
			
				|  |  | +  // });
 | 
	
		
			
				|  |  | +  // viewer.imageryLayers.addImageryProvider(tdtLayer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // // 天地图注记
 | 
	
		
			
				|  |  | +  // const tdtAnnotionLayer = new Cesium.WebMapTileServiceImageryProvider({
 | 
	
		
			
				|  |  | +  //   url: `http://t0.tianditu.com/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
 | 
	
		
			
				|  |  | +  //   layer: "tdtAnno",
 | 
	
		
			
				|  |  | +  //   style: "default",
 | 
	
		
			
				|  |  | +  //   format: "image/jpeg",
 | 
	
		
			
				|  |  | +  //   tileMatrixSetID: "w",
 | 
	
		
			
				|  |  | +  //   maximumLevel: 18,
 | 
	
		
			
				|  |  | +  //   show: false,
 | 
	
		
			
				|  |  | +  // });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    // 移除默认水印
 | 
	
		
			
				|  |  |    viewer.cesiumWidget.creditContainer.style.display = "none";
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -126,11 +145,95 @@ onMounted(() => {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    viewer.imageryLayers.addImageryProvider(tdtAnnotionLayer);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  // 添加点击事件处理
 | 
	
		
			
				|  |  | +  handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 在点击处理函数中增强错误处理
 | 
	
		
			
				|  |  | +handler.setInputAction((click) => {
 | 
	
		
			
				|  |  | +  const pickedObject = viewer.scene.pick(click.position);
 | 
	
		
			
				|  |  | +  
 | 
	
		
			
				|  |  | +  console.log('Picked object:', pickedObject); // 调试用,检查拾取对象
 | 
	
		
			
				|  |  | +  
 | 
	
		
			
				|  |  | +  if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
 | 
	
		
			
				|  |  | +    const entityId = pickedObject.id.id;
 | 
	
		
			
				|  |  | +    const data = entityDataMap.get(entityId) || pickedObject.id.properties?.data?.getValue();
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    console.log('Entity ID:', entityId); // 调试用,检查实体ID
 | 
	
		
			
				|  |  | +    console.log('Entity data:', data);   // 调试用,检查数据
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    if (data) {
 | 
	
		
			
				|  |  | +      // 显示弹框
 | 
	
		
			
				|  |  | +      selectedPoint.value = data;
 | 
	
		
			
				|  |  | +      popupPosition.value = {
 | 
	
		
			
				|  |  | +        x: click.position.x - 100,
 | 
	
		
			
				|  |  | +        y: click.position.y - 150
 | 
	
		
			
				|  |  | +      };
 | 
	
		
			
				|  |  | +      
 | 
	
		
			
				|  |  | +      // 聚焦到选中的点
 | 
	
		
			
				|  |  | +      viewer.flyTo(pickedObject.id, {
 | 
	
		
			
				|  |  | +        offset: new Cesium.HeadingPitchRange(0, -0.5, 1500)
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      console.warn('No data found for clicked entity');
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    // 点击空白区域
 | 
	
		
			
				|  |  | +    selectedPoint.value = null;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    // 清理函数
 | 
	
		
			
				|  |  |    onUnmounted(() => {
 | 
	
		
			
				|  |  | +    if (handler) {
 | 
	
		
			
				|  |  | +      handler.destroy();
 | 
	
		
			
				|  |  | +      handler = null;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      if (viewer && !viewer.isDestroyed()) {
 | 
	
		
			
				|  |  |        viewer.destroy();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    });
 | 
	
		
			
				|  |  |  })
 | 
	
		
			
				|  |  | -</script>  
 | 
	
		
			
				|  |  | +</script>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +<style scoped>
 | 
	
		
			
				|  |  | +.custom-popup {
 | 
	
		
			
				|  |  | +  position: absolute;
 | 
	
		
			
				|  |  | +  z-index: 1000;
 | 
	
		
			
				|  |  | +  display: none;
 | 
	
		
			
				|  |  | +  pointer-events: none;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +.popup-content {
 | 
	
		
			
				|  |  | +  background-color: white;
 | 
	
		
			
				|  |  | +  border-radius: 5px;
 | 
	
		
			
				|  |  | +  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
 | 
	
		
			
				|  |  | +  padding: 10px 15px;
 | 
	
		
			
				|  |  | +  width: 200px;
 | 
	
		
			
				|  |  | +  pointer-events: all;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +.popup-arrow {
 | 
	
		
			
				|  |  | +  position: absolute;
 | 
	
		
			
				|  |  | +  bottom: -10px;
 | 
	
		
			
				|  |  | +  left: 50%;
 | 
	
		
			
				|  |  | +  transform: translateX(-50%);
 | 
	
		
			
				|  |  | +  width: 0;
 | 
	
		
			
				|  |  | +  height: 0;
 | 
	
		
			
				|  |  | +  border-left: 10px solid transparent;
 | 
	
		
			
				|  |  | +  border-right: 10px solid transparent;
 | 
	
		
			
				|  |  | +  border-top: 10px solid white;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +.popup-content h3 {
 | 
	
		
			
				|  |  | +  margin-top: 0;
 | 
	
		
			
				|  |  | +  margin-bottom: 8px;
 | 
	
		
			
				|  |  | +  color: #333;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +.popup-content p {
 | 
	
		
			
				|  |  | +  margin: 5px 0;
 | 
	
		
			
				|  |  | +  color: #666;
 | 
	
		
			
				|  |  | +  font-size: 14px;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +</style>
 |