Explorar o código

修改了Cesium.vue:
添加了getScaleRatio()函数计算页面缩放比例
在点击事件中修正坐标:correctedX = click.position.x / scaleRatio

WQQ hai 1 mes
pai
achega
1b843eeb3f

+ 17 - 17
WebVue/TaiHufenglang/src/App.vue

@@ -7,23 +7,23 @@
 import { onMounted, onBeforeUnmount } from 'vue';
 import MapContainer from './components/MapContainer.vue';
 import Cesium from './components/Cesium.vue'
-// import autofit from 'autofit.js';
-
-// // // 初始化自动适配(Vue3组合式API写法)
-// // const initAutoFit = () => {
-// //   autofit.init({
-// //     designWidth: 1920,
-// //     designHeight: 1080,
-// //     el: '#app',
-// //     resize: true,
-// //     unit: 'px',
-// //     debug: false,
-// //     maxWidth: 1920,
-// //     maxHeight: 1080,
-// //     minFontSize: 12,
-// //     fontScale: true  // 启用字体缩放
-// //   });
-// // };
+import autofit from 'autofit.js';
+
+// 初始化自动适配(Vue3组合式API写法)
+const initAutoFit = () => {
+  autofit.init({
+    designWidth: 1920,
+    designHeight: 1080,
+    el: '#app',
+    resize: true,
+    unit: 'px',
+    debug: false,
+    maxWidth: 1920,
+    maxHeight: 1080,
+    minFontSize: 12,
+    fontScale: true  // 启用字体缩放
+  });
+};
 
 
 // 生命周期钩子

+ 64 - 83
WebVue/TaiHufenglang/src/components/Cesium.vue

@@ -3,8 +3,7 @@
   <!-- 自定义弹框组件 -->
   <div v-if="selectedPoint" class="custom-popup" :style="{
     left: `${popupPosition.x}px`,
-    top: `${popupPosition.y}px`,
-    display: selectedPoint ? 'block' : 'none'
+    top: `${popupPosition.y}px`
   }">
     <div class="popup-content">
       <h3>{{ selectedPoint.STNM || '未知点' }}</h3>
@@ -16,7 +15,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, onUnmounted, getCurrentInstance } from 'vue'
+import { ref, onMounted, onUnmounted } from 'vue'
 import * as Cesium from 'cesium';
 import "cesium/Build/CesiumUnminified/Widgets/widgets.css";
 import JYLData from '@/assets/Data/THJYL.json'
@@ -25,53 +24,46 @@ const TDTTK = "d9e7aa2ad204aba6aeedea6f5ab48ed9";
 const selectedPoint = ref(null);
 const popupPosition = ref({ x: 0, y: 0 });
 let handler = null;
+let viewer = null;
+
+// 计算页面缩放比例(与autofit配置一致)
+const getScaleRatio = () => {
+  const designWidth = 1920;
+  const designHeight = 1080;
+  return Math.min(window.innerWidth / designWidth, window.innerHeight / designHeight);
+};
 
 onMounted(() => {
-  const viewer = new Cesium.Viewer('cesiumContainer', {
+  viewer = new Cesium.Viewer('cesiumContainer', {
     timeline: false,
     baseLayer: false,
-    geocoder: false, // 隐藏搜索框
-    homeButton: false, // 隐藏Home按钮
-    sceneModePicker: false, // 隐藏场景模式选择器
-    navigationHelpButton: false, // 隐藏导航帮助按钮
-    animation: false, // 隐藏动画控件
-    fullscreenButton: false, // 隐藏全屏按钮
-    vrButton: false, // 隐藏VR按钮
+    geocoder: false,
+    homeButton: false,
+    sceneModePicker: false,
+    navigationHelpButton: false,
+    animation: false,
+    fullscreenButton: false,
+    vrButton: false,
     selectionIndicator: false,
     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 distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, 10000000);
+  const pointNearFarScalar = new Cesium.NearFarScalar(10000, 1.0, 1000000, 0.3);
+  const labelNearFarScalar = new Cesium.NearFarScalar(10000, 1.0, 400000, 0);
 
-  // 存储实体与数据的映射
+  // 存储实体与数据的映射(保持不变)
   const entityDataMap = new Map();
-
-  // 遍历数据并添加点和标签
   JYLData.forEach((item) => {
     const position = Cesium.Cartesian3.fromDegrees(
-      parseFloat(item.LGTD), // 经度 
-      parseFloat(item.LTTD)  // 纬度
+      parseFloat(item.LGTD),
+      parseFloat(item.LTTD)
     );
-
-    // 创建组合了图标和标签的实体
     const entity = viewer.entities.add({
       position: position,
       billboard: {
-        image: '/src/assets/icon/blue.png',  // 图标路径
+        image: '/src/assets/icon/blue.png',
         scale: 0.4,
         color: Cesium.Color.YELLOW,
         horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
@@ -97,18 +89,15 @@ onMounted(() => {
         distanceDisplayCondition: distanceDisplayCondition,
         scaleByDistance: labelNearFarScalar
       },
-      // 添加一个唯一ID用于识别
       id: `point-${item.STCD || item.LGTD + '-' + item.LTTD}`,
       properties: {
-        data: item  // 直接将数据附加到实体属性
+        data: item
       }
     });
-
-    // 存储实体与数据的映射关系
     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",
@@ -120,7 +109,6 @@ onMounted(() => {
   });
   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",
@@ -130,11 +118,10 @@ onMounted(() => {
     maximumLevel: 18,
     show: false,
   });
+  viewer.imageryLayers.addImageryProvider(tdtAnnotionLayer);
 
-  // 移除默认水印
+  // 初始化视图(保持不变)
   viewer.cesiumWidget.creditContainer.style.display = "none";
-
-  // 设置初始镜头位置(太湖)
   viewer.camera.setView({
     destination: Cesium.Cartesian3.fromDegrees(120.169103, 31.226174, 500000),
     orientation: {
@@ -143,64 +130,57 @@ 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
-      };
+  // 点击事件处理(核心修改)
+  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
+  handler.setInputAction((click) => {
+    const scaleRatio = getScaleRatio();
+    const correctedX = click.position.x / scaleRatio;
+    const correctedY = click.position.y / scaleRatio;
+    const pickedObject = viewer.scene.pick(new Cesium.Cartesian2(correctedX, correctedY));
+
+    if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
+      const entityId = pickedObject.id.id;
+      const data = entityDataMap.get(entityId) || pickedObject.id.properties?.data?.getValue();
       
-      // 聚焦到选中的点
-      viewer.flyTo(pickedObject.id, {
-        offset: new Cesium.HeadingPitchRange(0, -0.5, 1500)
-      });
+      if (data) {
+        selectedPoint.value = data;
+        // 关键:计算图标屏幕坐标,固定显示在图标上方
+        const entityPosition = viewer.scene.cartesianToCanvasCoordinates(pickedObject.id.position._value);
+        if (entityPosition) {
+          popupPosition.value = {
+            // 水平居中对齐图标
+            x: (entityPosition.x / scaleRatio) - 100,
+            // 固定显示在图标上方(距离图标底部10px)
+            y: (entityPosition.y / scaleRatio) - 130  // 130 = 弹框高度 + 间距
+          };
+        }
+        viewer.flyTo(pickedObject.id, {
+          offset: new Cesium.HeadingPitchRange(0, -0.5, 1500)
+        });
+      }
     } else {
-      console.warn('No data found for clicked entity');
+      selectedPoint.value = null;
     }
-  } else {
-    // 点击空白区域
-    selectedPoint.value = null;
-  }
-}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
 
-  // 清理函数
+  // 清理函数(移除鼠标移动监听)
   onUnmounted(() => {
     if (handler) {
       handler.destroy();
       handler = null;
     }
-
     if (viewer && !viewer.isDestroyed()) {
       viewer.destroy();
     }
   });
-})
+});
 </script>
 
 <style scoped>
 .custom-popup {
   position: absolute;
   z-index: 1000;
-  display: none;
+  display: block; /* 始终显示(由v-if控制显隐) */
   pointer-events: none;
 }
 
@@ -215,7 +195,7 @@ handler.setInputAction((click) => {
 
 .popup-arrow {
   position: absolute;
-  bottom: -10px;
+  bottom: -10px; /* 指向图标 */
   left: 50%;
   transform: translateX(-50%);
   width: 0;
@@ -225,6 +205,7 @@ handler.setInputAction((click) => {
   border-top: 10px solid white;
 }
 
+/* 其他样式保持不变 */
 .popup-content h3 {
   margin-top: 0;
   margin-bottom: 8px;

+ 43 - 19
WebVue/TaiHufenglang/src/components/MapContainer.vue

@@ -22,25 +22,49 @@ import Rightmoudle from './rightmodul.vue'
 import Middlemoudle from './middlemodul.vue'
 import Cesium from './Cesium.vue'
 import PixelStreaming from './UEpix.vue'
-import autofit from 'autofit.js';
-
-
-
-// 初始化自动适配(Vue3组合式API写法)
-const initAutoFit = () => {
-  autofit.init({
-    designWidth: 1920,
-    designHeight: 1080,
-    el: '#app',
-    resize: true,
-    unit: 'px',
-    debug: false,
-    maxWidth: 1920,
-    maxHeight: 1080,
-    minFontSize: 12,
-    fontScale: true  // 启用字体缩放
-  });
-};
+// import autofit from 'autofit.js';
+
+
+
+// // 初始化自动适配(Vue3组合式API写法)
+// const initAutoFit = () => {
+//   autofit.init({
+//     designWidth: 1920,
+//     designHeight: 1080,
+//     el: '.content',
+//     resize: true,
+//     unit: 'px',
+//     debug: false,
+//     maxWidth: 1920,
+//     maxHeight: 1080,
+//     minFontSize: 12,
+//     fontScale: true  // 启用字体缩放
+//   });
+// };
+
+// // 生命周期钩子
+// onMounted(() => {
+//   initAutoFit();
+//   window.addEventListener('resize', handleResize);
+// });
+
+// onBeforeUnmount(() => {
+//   window.removeEventListener('resize', handleResize);
+// });
+
+// // 防抖处理resize事件
+// const handleResize = () => {
+//   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>