| | |
| | | <div style="display: flex;justify-content: space-between;"> |
| | | <!-- 选点按钮 --> |
| | | <div @click="togglePick" :class="['pick-button', { active: isPickingActive }]"> |
| | | <img src="@/assets/img/timeline/坐标.png" style="width: 26px;height: 26px;" /> |
| | | <!-- <span v-if="isPickingActive">停止拾取</span> |
| | | <span v-else>开始拾取</span> --> |
| | | <img v-if="!isPickingActive" src="@/assets/img/timeline/流速.png" style="width: 28px;height: 28px;" /> |
| | | <img v-else src="@/assets/img/timeline/已流速.png" style="width: 28px;height: 28px;" /> |
| | | </div> |
| | | <!-- 开始计算按钮 --> |
| | | <!-- <div @click="startCalculation"> |
| | | <img src="@/assets/img/timeline/水位.png" style="margin-top: -4px;width: 34px;height: 34px;" /> |
| | | </div> --> |
| | | <!-- 结束计算按钮 --> |
| | | <div @click="endCalculation"> |
| | | <img src="@/assets/img/timeline/清除.png" style="width: 26px;height: 26px;" /> |
| | | </div> |
| | |
| | | <script setup> |
| | | import { defineProps, watch, ref, onMounted, defineExpose } from "vue"; |
| | | import { ElMessage } from 'element-plus'; |
| | | import { getFlowRate } from "@/api/trApi.js"; |
| | | import { useSimStore } from "@/store/simulation"; |
| | | import { storeToRefs } from "pinia"; |
| | | const simStore = useSimStore(); |
| | | const { selectedScheme } = storeToRefs(simStore); |
| | | |
| | | const pickedPoints = ref([]); |
| | | const handler = ref(null); |
| | | const isPickingActive = ref(false); |
| | | const currentTime = ref(0); |
| | | let serviceInfo = ref(null); |
| | | |
| | | const props = defineProps({ |
| | | playingTime: { |
| | |
| | | } |
| | | }); |
| | | |
| | | watch( |
| | | () => props.playingTime, |
| | | (newVal) => { |
| | | currentTime.value = newVal; |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | // Cesium viewer 初始化相关逻辑 |
| | | const viewer = window.viewer; |
| | | |
| | | function getPickPosition(windowPosition) { |
| | |
| | | } |
| | | function addPointToViewer(point, index) { |
| | | const displayTime = currentTime.value || "未设置时间"; |
| | | const schemeInfo = selectedScheme.value; |
| | | serviceInfo = schemeInfo.serviceName; |
| | | |
| | | // 添加标签(确保实体创建时包含label属性) |
| | | // 创建 label 实体 |
| | | const labelEntity = viewer.entities.add({ |
| | | position: point.cartesian, |
| | | label: { |
| | | text: `测量点 ${index + 1}\n经度: ${point.longitude.toFixed(6)}\n纬度: ${point.latitude.toFixed(6)}\n时间: ${displayTime}`, |
| | | font: '14pt monospace', |
| | | text: `测量点 ${pickedPoints.value.length + 1}\n水深: 等待启动...\n流速: 等待启动...`, |
| | | font: 'bold 14pt monospace', |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | fillColor: Cesium.Color.YELLOW, |
| | | outlineColor: Cesium.Color.BLACK, |
| | |
| | | showBackground: true, |
| | | scale: 1, |
| | | distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000), |
| | | pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 5000, 0.3) |
| | | pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 5000, 0.3), |
| | | } |
| | | }); |
| | | const groundPosition = Cesium.Cartesian3.fromRadians( |
| | | point.longitude * Math.PI / 180, |
| | | point.latitude * Math.PI / 180, |
| | | 0 |
| | | ); |
| | | const cylinderEntity = viewer.entities.add({ |
| | | position: groundPosition, // 底部位置 |
| | | cylinder: { |
| | | length: 190.0, |
| | | topRadius: 1.0, |
| | | bottomRadius: 1.0, |
| | | material: Cesium.Color.YELLOW, |
| | | outline: true, |
| | | outlineColor: Cesium.Color.YELLOW, |
| | | slices: 32, |
| | | heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND, |
| | | distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000) |
| | | } |
| | | }); |
| | | |
| | | // 添加垂直线 |
| | | const lineEntity = viewer.entities.add({ |
| | | polyline: { |
| | | positions: [point.cartesian, Cesium.Cartesian3.fromRadians(point.longitude * Math.PI / 180, point.latitude * Math.PI / 180, 0)], |
| | | width: 2, |
| | | material: new Cesium.PolylineOutlineMaterialProperty({ |
| | | color: Cesium.Color.RED.withAlpha(0.8), |
| | | outlineColor: Cesium.Color.WHITE, |
| | | outlineWidth: 4 |
| | | }), |
| | | distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000), |
| | | pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 5000, 0.3) |
| | | } |
| | | // 请求数据并更新 label |
| | | getFlowRateInfo(point.longitude, point.latitude, displayTime).then(result => { |
| | | updateLabel(pickedPoints.value.length - 1, result.depth, result.velocity); |
| | | }); |
| | | |
| | | // 保存 labelEntity 和 lineEntity |
| | | // 存储实体引用 |
| | | pickedPoints.value.push({ |
| | | labelEntity, |
| | | lineEntity, |
| | | cylinderEntity, // 使用圆柱代替 line 和 circle |
| | | longitude: point.longitude, |
| | | latitude: point.latitude |
| | | }); |
| | |
| | | |
| | | function initPickHandler() { |
| | | if (!viewer?.scene?.canvas) return; |
| | | |
| | | if (handler.value) { |
| | | handler.value.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); |
| | | handler.value.destroy(); |
| | | handler.value = null; |
| | | } |
| | | |
| | | handler.value = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); |
| | | |
| | | handler.value.setInputAction((movement) => { |
| | |
| | | if (position) { |
| | | const index = pickedPoints.value.length; |
| | | addPointToViewer(position, index); |
| | | console.log('执行加点工作'); |
| | | |
| | | } |
| | | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); |
| | | } |
| | | |
| | | function startPicking() { |
| | | // pickedPoints.value = []; |
| | | // viewer.entities.removeAll(); |
| | | if (!handler.value) { |
| | | initPickHandler(); // 只有第一次才初始化 |
| | | initPickHandler(); |
| | | } |
| | | |
| | | isPickingActive.value = true; |
| | | ElMessage.success('开始拾取坐标,请点击地图选择点位!'); |
| | | ElMessage.success(`开始--流量流速--拾取坐标功能,请点击地图选择点位!选取完请及时关闭,避免影响其他功能!`); |
| | | } |
| | | |
| | | function stopPicking() { |
| | | if (handler.value) { |
| | | handler.value.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); |
| | |
| | | |
| | | function togglePick() { |
| | | if (isPickingActive.value) { |
| | | stopPicking(); // 调用 stopPicking 来正确地停止选取过程 |
| | | isPickingActive.value = false; // 确保 isPickingActive 设置为 false |
| | | ElMessage.success('当前坐标已选取完成!水位流速测量准备完毕!'); |
| | | stopPicking(); |
| | | isPickingActive.value = false; |
| | | ElMessage.info('已关闭--流量流速--拾取点坐标功能!'); |
| | | console.log(pickedPoints.value, '最终选取的点'); |
| | | } else { |
| | | startPicking(); |
| | | isPickingActive.value = true; // 在开始选取前设置为 true |
| | | isPickingActive.value = true; |
| | | } |
| | | } |
| | | // 当 currentTime 改变时更新所有点的 label 中的时间戳 |
| | | // 修改watch逻辑 |
| | | watch( |
| | | () => props.playingTime, |
| | | (newVal) => { |
| | | currentTime.value = newVal || "未设置时间"; |
| | | updateAllLabels(); |
| | | async (newVal, oldVal) => { |
| | | if (newVal !== oldVal) { |
| | | currentTime.value = newVal || "未设置时间"; |
| | | await updateAllLabels(); |
| | | } |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | |
| | | function updateAllLabels() { |
| | | pickedPoints.value.forEach((pointInfo, index) => { |
| | | if (pointInfo.labelEntity && pointInfo.labelEntity.label) { |
| | | pointInfo.labelEntity.label.text = |
| | | `测量点 ${index + 1}\n经度: ${pointInfo.longitude.toFixed(6)}\n纬度: ${pointInfo.latitude.toFixed(6)}\n时间: ${currentTime.value}`; |
| | | } |
| | | }); |
| | | async function updateAllLabels() { |
| | | for (const pointInfo of pickedPoints.value) { |
| | | if (!pointInfo || !pointInfo.labelEntity) continue; |
| | | |
| | | const result = await getFlowRateInfo(pointInfo.longitude, pointInfo.latitude, currentTime.value); |
| | | updateLabel(pointInfo, result.depth, result.velocity); |
| | | } |
| | | } |
| | | |
| | | function startCalculation() { |
| | | console.log('选取的坐标点:', pickedPoints.value); |
| | | console.log(`当前时间:${currentTime.value}`); |
| | | function updateLabel(pointInfo, depth, velocity) { |
| | | if (pointInfo.labelEntity && pointInfo.labelEntity.label) { |
| | | pointInfo.labelEntity.label.text = ` |
| | | 测量点 ${pickedPoints.value.findIndex(p => p === pointInfo) + 1} |
| | | 水深: ${depth} m |
| | | 流速: ${velocity} m/s |
| | | `.trim(); |
| | | } |
| | | } |
| | | |
| | | function endCalculation() { |
| | | // console.log('由本功能创建的所有 label 和 polyline entities:'); |
| | | // pickedPoints.value.forEach((pointInfo, index) => { |
| | | // console.log(`测量点 ${index + 1}:`); |
| | | // console.log('Label Entity:', pointInfo.labelEntity); |
| | | // console.log('Polyline Entity:', pointInfo.lineEntity); |
| | | // }); |
| | | // console.log('当前 Cesium 中所有实体列表:'); |
| | | // viewer.entities.values.forEach((entity, idx) => { |
| | | // console.log(`实体 #${idx}:`, entity); |
| | | // }); |
| | | pickedPoints.value.forEach(pointInfo => { |
| | | if (pointInfo.labelEntity) viewer.entities.remove(pointInfo.labelEntity); |
| | | if (pointInfo.lineEntity) viewer.entities.remove(pointInfo.lineEntity); |
| | | if (pointInfo.cylinderEntity) viewer.entities.remove(pointInfo.cylinderEntity); |
| | | }); |
| | | pickedPoints.value = []; |
| | | } |
| | | defineExpose({ |
| | | endCalculation |
| | | endCalculation, |
| | | stopPicking |
| | | }); |
| | | |
| | | function getFlowRateInfo(lon, lat, time) { |
| | | const params = { |
| | | lon: lon, |
| | | lat: lat, |
| | | time: time, |
| | | serviceName: serviceInfo |
| | | }; |
| | | return getFlowRate(params).then(data => { |
| | | // console.log('获取到的数据:', data); |
| | | if (data && data.code === 200) { |
| | | return { |
| | | depth: data.data.depth.toFixed(2), |
| | | velocity: data.data.velocity.toFixed(2) |
| | | }; |
| | | } else { |
| | | return { depth: 'N/A', velocity: 'N/A' }; |
| | | } |
| | | }).catch(error => { |
| | | console.error('获取数据时发生错误:', error); |
| | | return { depth: 'N/A', velocity: 'N/A' }; |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | <style lang="less" scoped></style> |