您的位置:首页 > 房产 > 家装 > 【Cesium开发实战】飞行漫游功能的实现,可设置漫游路径,漫游高度,暂停,继续,删除路径

【Cesium开发实战】飞行漫游功能的实现,可设置漫游路径,漫游高度,暂停,继续,删除路径

2024/12/22 14:39:10 来源:https://blog.csdn.net/qq_34512796/article/details/140342378  浏览:    关键词:【Cesium开发实战】飞行漫游功能的实现,可设置漫游路径,漫游高度,暂停,继续,删除路径

Cesium有很多很强大的功能,可以在地球上实现很多炫酷的3D效果。今天给大家分享一个可自定义的漫游飞行功能。

1.话不多说,先展示

漫游

2.设计思路

项目需求,可自定义漫游路径,并且设置高度,暂停,继续,删除等功能。点击绘制开始在地图上绘制漫游的路径点位,双击结束后可编辑漫游路径名和漫游的高度设置。点击飞行,创建模型,使模型按照设定的点位和高度进行漫游。

3.具体代码

<template><div class="page"><el-button @click="drawLineRoad">绘制</el-button><el-table :data="dataList" border><el-table-column prop="name" label="名称" align="center" /><el-table-column prop="action" label="操作" align="center"><template #default="scope"><el-button type="primary" style="width: 30px" @click="startFly(scope.row, scope.$index)">飞行</el-button><el-button type="primary" style="width: 30px" @click="stopFly()">暂停</el-button><el-button type="primary" style="width: 30px" @click="continueFly()">继续</el-button><el-button link type="primary" size="small" @click="delEntity(scope.row, scope.$index)"><el-icon :size="16"><ele-Delete /> </el-icon></el-button></template></el-table-column></el-table></div><el-dialog v-model="dialogFormVisible" title="配置" width="500" :close-on-press-escape="false" :close-on-click-modal="false" :show-close="false"><el-form ref="formRef" :model="form" label-width="auto" :rules="rules"><el-form-item label="漫游路径名称" prop="title"><el-input v-model="form.title" placeholder="请输入" /></el-form-item><el-form-item label="漫游高度"><el-input-number :min="0" v-model="form.height" placeholder="请输入" /></el-form-item></el-form><template #footer><div class="dialog-footer"><el-button type="primary" @click="submitForm(formRef)"> 确定 </el-button></div></template></el-dialog>
</template><script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref } from 'vue';
import { Cesium } from '/@/utils/cesium';const props = defineProps(['viewer']);const dialogFormVisible = ref(false);var handler: any = null;const formRef = ref();const rules = {title: { required: true, message: '请输入漫游路径名称', trigger: 'blur' },
};//漫游名称
const form = reactive({title: '',height: 300,
});//是否开始绘制
const drawing = ref(false);//列表数据
const dataList: any = reactive([]);//绘制的所有地面的点线实体集合
var entities: any = [];
//临时一条数据的point实体列表
var pointEntities: any = [];
//临时一条数据的线实体列表
var linesEntities: any = [];var activeShapePoints: any = [];
//构建列表一条数据的数据,经纬度高度。
var customMarks: any = [];var floatingPoint: any = undefined;
var activeShape: any = undefined;//绘制线路
const drawLineRoad = () => {drawing.value = true;handler = new Cesium.ScreenSpaceEventHandler(props.viewer.scene.canvas);//鼠标左键handler.setInputAction(function (event: any) {if (drawing.value) {var earthPosition = props.viewer.scene.pickPosition(event.position);if (Cesium.defined(earthPosition)) {if (activeShapePoints.length === 0) {floatingPoint = createPoint(earthPosition);activeShapePoints.push(earthPosition);var dynamicPositions = new Cesium.CallbackProperty(function () {return activeShapePoints;}, false);activeShape = drawShape(dynamicPositions); //绘制动态图//线实体集合linesEntities.push(activeShape);}activeShapePoints.push(earthPosition);//点实体集合pointEntities.push(createPoint(earthPosition));}}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);//鼠标移动handler.setInputAction(function (event: any) {if (Cesium.defined(floatingPoint)) {var newPosition = props.viewer.scene.pickPosition(event.endPosition);if (Cesium.defined(newPosition)) {floatingPoint.position.setValue(newPosition);activeShapePoints.pop();activeShapePoints.push(newPosition);}}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);handler.setInputAction(function () {if (drawing.value) {drawing.value = false;terminateShape();}}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
};//绘制点
const createPoint = (worldPosition: any) => {var point = props.viewer.entities.add({position: worldPosition,point: {color: Cesium.Color.RED,pixelSize: 10,heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,},});return point;
};//绘制线
const drawShape = (positionData: any) => {var shape = props.viewer.entities.add({polyline: {with: 10,color: Cesium.Color.RED,positions: positionData,clampToGround: true,},});return shape;
};//双击后处理数据
const terminateShape = () => {linesEntities.push(drawShape(activeShapePoints)); //绘制最终图//因双击会触发俩次单机事件,去除最后一个点重复绘制,并删除多余的点props.viewer.entities.remove(pointEntities[pointEntities.length - 1]);pointEntities.pop();dialogFormVisible.value = true; //弹出对话框props.viewer.entities.remove(floatingPoint); //去除动态点图形(当前鼠标点)props.viewer.entities.remove(activeShape); //去除动态图形floatingPoint = undefined;activeShape = undefined;activeShapePoints = [];props.viewer.trackedEntity = null;
};/*** 点击确定*/
const submitForm = async (formEl: any) => {const valid = await formEl.validate();if (valid) {//创建条目列表数据if (pointEntities.length) {for (const item of pointEntities) {const latitude = toDegrees(Cesium.Cartographic.fromCartesian(item.position._value).latitude);const longitude = toDegrees(Cesium.Cartographic.fromCartesian(item.position._value).longitude);customMarks.push({ longitude: longitude, latitude: latitude, height: form.height });}}addElectronicFence(form.title, customMarks);customMarks = [];//重置默认高度form.height = 300;dialogFormVisible.value = false;formEl.resetFields();}
};/*** 添加列表数据*/
var addElectronicFence = (name: string, positions: any) => {//点实体和线实体的集合entities.push({pointEntities: pointEntities,linesEntities: linesEntities,});dataList.push({id: Cesium.createGuid(),name: name,positions: positions,});pointEntities = [];linesEntities = [];//移除点击事件handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
};/*** 删除已绘制的图形*/
const delEntity = (item: any, index: number) => {//如果删除的是当前飞行的路线 暂停飞行并删除飞机实体if (item.id == airplaneEntity.id) {stopFly();props.viewer.entities.remove(airplaneEntity);}//循环删除条目上的实体点  和  实体线for (const obj of entities[index].pointEntities) {props.viewer.entities.remove(obj);}for (const obj of entities[index].linesEntities) {props.viewer.entities.remove(obj);}//删除当前条目的数据entities.splice(index, 1);dataList.splice(index, 1);
};const positionProperty = new Cesium.SampledPositionProperty();
// 时间的间隔
const timeStepInSeconds = 10;
var airplaneEntity: any;//开始飞行
const startFly = (item: any, index: number) => {//当下个飞行前清除上次的飞行对象和路径if (airplaneEntity != null) {props.viewer.entities.remove(airplaneEntity);}//获取条目经纬度数据集合let flightData = item.positions;const totalSeconds = (flightData.length - 1) * timeStepInSeconds;// 设置起点时间const time = new Date('2020-03-09T23:10:00Z');const start = Cesium.JulianDate.fromDate(time);// 设置终点时间const stop = Cesium.JulianDate.addSeconds(start, totalSeconds, new Cesium.JulianDate());props.viewer.clock.startTime = start.clone();props.viewer.clock.stopTime = stop.clone();props.viewer.clock.currentTime = start.clone();// 设置进度条,从哪里开始到哪里结束props.viewer.timeline.zoomTo(start, stop);for (let i = 0; i < flightData.length; i++) {const dataPoint = flightData[i];// 采样时间const time = Cesium.JulianDate.addSeconds(start, i * timeStepInSeconds, new Cesium.JulianDate());// 计算当前的3D坐标const position = Cesium.Cartesian3.fromDegrees(dataPoint.longitude, dataPoint.latitude, dataPoint.height);// 添加轨迹采样点positionProperty.addSample(time, position);// 添加物体点// props.viewer.entities.add({// 	position: position,// 	point: {// 		pixelSize: 10,// 		color: new Cesium.Color(0.7, 0.8, 0, 0.7),// 	},// });}// 创建飞机airplaneEntity = props.viewer.entities.add({id: item.id,availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({start: start,stop: stop,}),]),position: positionProperty,model: {uri: '/src/assets/cesium/Cesium_Air.glb',},// 自动计算前进方向orientation: new Cesium.VelocityOrientationProperty(positionProperty),// 绘制轨迹线path: new Cesium.PathGraphics({width: 3,}),});// 设置相机追踪运动物体props.viewer.trackedEntity = airplaneEntity;// 设置时间速率props.viewer.clock.multiplier = 1;// 设置自动播放props.viewer.clock.shouldAnimate = true;// setTimeout(() => {// 	props.viewer.clock.shouldAnimate = true;// }, 5000);
};
//停止飞行
const stopFly = () => {props.viewer.clock.shouldAnimate = false;
};
//继续飞行
const continueFly = () => {props.viewer.clock.shouldAnimate = true;
};// 弧度转角度
const toDegrees = (radians: any) => {return (radians * 180) / Math.PI;
};
// 角度转弧度
const toRadians = (degrees: any) => {return (degrees * Math.PI) / 180;
};onMounted(() => {});onUnmounted(() => {//清除绘制的内容props.viewer.entities.removeAll();if (handler != null) {handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);}
});
</script><style scoped>
.page {position: absolute;right: 10px;top: 10px;color: #fff;background: #fff;padding: 10px;border-radius: 5px;width: 400px;
}
</style>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com