功能介绍:在地图上手动绘制站点,并在站点间生成飞行路线,点击开始按钮沿飞行路线进行飞行,在每个站点停顿一段时间后继续向下一个站点飞行。可再飞行过程中跳转到任意站点继续完成飞行。
代码:
<div>
<el-checkbox v-model="isLineVisible" @change="toggleLineVisibility" class="flex-container-left"
label="是否显示路线" size="large" />
<el-checkbox @change="toggleStopVisibility" v-model="isStopVisible" label="是否显示站点" size="large" />
</div>
<div class="selectdrop">
<span
:style="{ color: 'white', position: 'absolute', top: '4.5rem', left: '1.0625rem', fontSize: '14px', fontFamily: 'Source' }">站点</span>
<el-select v-model="index" id="stopList" popper-class="custom-select" placeholder="请选择站点"
:teleported="false">
<el-option v-for="item in allIndex" :key="item.value" :label="item.label" :value="item.value"
@click="changesite">
</el-option>
</el-select>
</div>
<div @click="addPoint" class="content-button"
:style="{ height: '1.9375rem', left: ' 2.1375rem', bottom: '4.9375rem' }">
添加站点
</div>
<div @click="play" class="content-button"
:style="{ height: '1.9375rem', right: ' 2.1375rem', bottom: '4.9375rem' }">
开始
</div>
<div @click="pause" class="content-button"
:style="{ height: '1.9375rem', left: '2.1375rem', bottom: '1.9375rem', backgroundColor: '#6C8DAE', border: '1px solid #6C8DAE' }">
暂停
</div>
<div @click="stop" class="content-button"
:style="{ height: '1.9375rem', right: ' 2.1375rem', bottom: '1.9375rem', backgroundColor: '#B73A3A', border: '0', }">
结束
</div>
<script setup>
const isStopVisible = ref(false);
const isLineVisible = ref(false);
const entities = [];
const lineEntities = [];
// 添加站点
const addPoint = () => {
const handler = new Cesium.ScreenSpaceEventHandler(window.viewer.scene.canvas);
handler.setInputAction((click) => {
const cartesian = window.viewer.camera.pickEllipsoid(click.position, window.viewer.scene.globe.ellipsoid);
if (cartesian) {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const lon = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const newSite = { label: `站点${allIndex.length + 1}`, value: allIndex.length, position: { lon, lat } };
allIndex.push(newSite);
addEntities();
}
handler.destroy();
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
};
// 站点显隐控制
const toggleStopVisibility = () => {
entities.forEach(entity => {
entity.show = isStopVisible.value;
});
};
// 路线显隐控制
const toggleLineVisibility = () => {
lineEntities.forEach(entity => {
entity.show = isLineVisible.value;
});
};
const handleCloseModal = () => {
visible.value = false;
// 移除地图上的路线和站点
entities.forEach(entity => {
viewer.entities.remove(entity);
});
lineEntities.forEach(lineEntity => {
viewer.entities.remove(lineEntity);
});
entities.length = 0;
lineEntities.length = 0;
};
const addEntities = () => {
// 清除现有站点和路线
entities.forEach(entity => viewer.entities.remove(entity));
lineEntities.forEach(lineEntity => viewer.entities.remove(lineEntity));
entities.length = 0;
lineEntities.length = 0;
// 添加站点标记
allIndex.forEach(site => {
const entity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(site.position.lon, site.position.lat, 100),
point: {
pixelSize: 10,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
},
});
entities.push(entity);
});
// 生成站点之间的路线
for (let i = 0; i < allIndex.length - 1; i++) {
const start = allIndex[i].position;
const end = allIndex[i + 1].position;
const lineEntity = viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights([
start.lon, start.lat, 100,
end.lon, end.lat, 100
]),
width: 5,
material: Cesium.Color.YELLOW,
},
show: isLineVisible.value
});
lineEntities.push(lineEntity);
}
// 初始化时根据 isStopVisible 的值设置站点的显示/隐藏
toggleStopVisibility();
// 初始化时根据 isLineVisible 的值设置路线的显示/隐藏
toggleLineVisibility();
};
watch(() => visible.value, (newVal) => {
if (newVal) {
addEntities();
}
emits("update:visible", newVal);
});
watch(() => props.visible, (newVal) => {
visible.value = props.visible;
if (visible.value) {
addEntities();
}
});
watch(isStopVisible, (newVal) => {
toggleStopVisibility();
});
watch(isLineVisible, (newVal) => {
toggleLineVisibility();
});
const changesite = () => {
// 获取当前选择的站点
const selectedSite = allIndex[index.value];
const nextSite = allIndex[index.value + 1] || allIndex[index.value]; // 获取下一个站点,如果没有下一个站点则朝向当前站点
if (selectedSite) {
stop(); // 停止当前飞行
currentIndex = index.value; // 设置当前索引为新选择的站点
// 计算heading朝向
const heading = computeHeading(selectedSite.position, nextSite.position);
// 跳转到选择的站点并设置视线朝向下一个站点
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(selectedSite.position.lon, selectedSite.position.lat, 200),
orientation: {
heading: heading,
pitch: Cesium.Math.toRadians(-30), // 设置视线的俯仰角
roll: 0.0
},
duration: 1 // 设置一个较短的飞行时间
});
}
}