1
wangjuncheng
2025-05-23 5ad5f4caf07ec82bc6fb24fc94282e3ad59b3261
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
<template>
    <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> -->
        </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>
    </div>
</template>
 
<script setup>
import { defineProps, watch, ref, onMounted, defineExpose } from "vue";
import { ElMessage } from 'element-plus';
 
const pickedPoints = ref([]);
const handler = ref(null);
const isPickingActive = ref(false);
const currentTime = ref(0);
 
const props = defineProps({
    playingTime: {
        type: String,
        required: true
    }
});
 
watch(
    () => props.playingTime,
    (newVal) => {
        currentTime.value = newVal;
    },
    { immediate: true }
);
// Cesium viewer 初始化相关逻辑
const viewer = window.viewer;
 
function getPickPosition(windowPosition) {
    if (!viewer) return null;
    viewer.scene.globe.depthTestAgainstTerrain = true;
    const cartesian = viewer.scene.pickPosition(windowPosition);
    if (!cartesian) return null;
    const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
    cartographic.height += 200.0;
    return {
        cartesian: Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height),
        longitude: Cesium.Math.toDegrees(cartographic.longitude),
        latitude: Cesium.Math.toDegrees(cartographic.latitude),
        height: cartographic.height
    };
}
function addPointToViewer(point, index) {
    const displayTime = currentTime.value || "未设置时间";
 
    // 添加标签(确保实体创建时包含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',
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            fillColor: Cesium.Color.YELLOW,
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 2,
            verticalOrigin: Cesium.VerticalOrigin.CENTER,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            backgroundColor: Cesium.Color.fromCssColorString('rgba(0,0,0,0.7)'),
            backgroundPadding: new Cesium.Cartesian2(10, 10),
            showBackground: true,
            scale: 1,
            distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000),
            pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 5000, 0.3)
        }
    });
 
    // 添加垂直线
    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)
        }
    });
 
    // 保存 labelEntity 和 lineEntity
    pickedPoints.value.push({
        labelEntity,
        lineEntity,
        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) => {
        const position = getPickPosition(movement.position);
        if (position) {
            const index = pickedPoints.value.length;
            addPointToViewer(position, index);
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
 
function startPicking() {
    // pickedPoints.value = [];
    // viewer.entities.removeAll();
    if (!handler.value) {
        initPickHandler(); // 只有第一次才初始化
    }
 
    isPickingActive.value = true;
    ElMessage.success('开始拾取坐标,请点击地图选择点位!');
}
 
function stopPicking() {
    if (handler.value) {
        handler.value.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
        handler.value.destroy();
        handler.value = null;
    }
    isPickingActive.value = false;
}
 
function togglePick() {
    if (isPickingActive.value) {
        stopPicking(); // 调用 stopPicking 来正确地停止选取过程
        isPickingActive.value = false; // 确保 isPickingActive 设置为 false
        ElMessage.success('当前坐标已选取完成!水位流速测量准备完毕!');
        console.log(pickedPoints.value, '最终选取的点');
    } else {
        startPicking();
        isPickingActive.value = true; // 在开始选取前设置为 true
    }
}
// 当 currentTime 改变时更新所有点的 label 中的时间戳
// 修改watch逻辑
watch(
    () => props.playingTime,
    (newVal) => {
        currentTime.value = newVal || "未设置时间";
        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}`;
        }
    });
}
 
function startCalculation() {
    console.log('选取的坐标点:', pickedPoints.value);
    console.log(`当前时间:${currentTime.value}`);
}
 
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);
    });
    pickedPoints.value = [];
}
defineExpose({
    endCalculation
});
 
</script>
 
<style lang="less" scoped></style>