Browse Source

双击图标转跳位置

WQQ 1 month ago
parent
commit
8ec40e511e

+ 12 - 2
WebVue/TaiHufenglang/src/App.vue

@@ -23,6 +23,7 @@ const initAutoFit = () => {
   });
 };
 
+
 // 生命周期钩子
 onMounted(() => {
   initAutoFit();
@@ -35,9 +36,18 @@ onBeforeUnmount(() => {
 
 // 防抖处理resize事件
 const handleResize = () => {
-  // 使用autofit自带resize方法
-  autofit.resize();
+  if (typeof autofit === 'undefined') {
+    console.error('autofit is not defined');
+    return;
+  }
+  // 确保autofit对象有resize方法
+  if (typeof autofit.resize === 'function') {
+    autofit.resize();
+  } else {
+    console.error('autofit.resize is not a function');
+  }
 };
+
 </script>
 
 <style>

+ 25 - 0
WebVue/TaiHufenglang/src/assets/css/index.css

@@ -224,4 +224,29 @@
   .panel-column {
     max-width: 90%;
   }
+}
+
+/* Cesium图标弹框样式 */
+.custom-popup {
+  position: absolute;
+  z-index: 1000;
+  display: none;
+  pointer-events: none;
+  transition: opacity 0.2s ease; /* 添加过渡效果 */
+}
+
+.custom-popup.active {
+  display: block;
+}
+
+/* 确保弹框不会超出视口 */
+.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;
+  max-width: 300px;
+  word-wrap: break-word;
 }

+ 137 - 34
WebVue/TaiHufenglang/src/components/Cesium.vue

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