当前位置: 首页 > news >正文

【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>

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python爬虫并输出
  • 在若依框架基础上开发新功能
  • 基于YOLOV8的数粒机视觉计数解决方案
  • C# 实现基于exe内嵌HTTPS监听服务、从HTTP升级到HTTPS 后端windows服务
  • 【C++】CMake入门
  • React_自定义组件_下拉框
  • 面试题009-Java-MyBatis
  • 【Python】Requests 库使用示例
  • Maven 项目编译提示 unparseable pom 的解决方法
  • 练习:随机点名器5
  • 数据结构与算法基础-学习-37-平衡二叉树(Avl树)之删除节点
  • 各向异性含水层中地下水三维流基本微分方程的推导(二)
  • @Autowired 和 @Resource 区别的补充说明与示例
  • Datadomain存储上的文件大小,linux环境建议使用du -sh --apparent-size或ll -sh来查看
  • 【JAVA入门】Day15 - 接口
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • Codepen 每日精选(2018-3-25)
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • JAVA多线程机制解析-volatilesynchronized
  • JAVA之继承和多态
  • Mybatis初体验
  • Python连接Oracle
  • Ruby 2.x 源代码分析:扩展 概述
  • SQLServer插入数据
  • tweak 支持第三方库
  • underscore源码剖析之整体架构
  • Vue--数据传输
  • windows下使用nginx调试简介
  • 技术发展面试
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 数组的操作
  • 跳前端坑前,先看看这个!!
  • 主流的CSS水平和垂直居中技术大全
  • ​​​​​​​​​​​​​​Γ函数
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • ​十个常见的 Python 脚本 (详细介绍 + 代码举例)
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • ###项目技术发展史
  • #mysql 8.0 踩坑日记
  • (4)logging(日志模块)
  • (52)只出现一次的数字III
  • (BAT向)Java岗常问高频面试汇总:MyBatis 微服务 Spring 分布式 MySQL等(1)
  • (CVPRW,2024)可学习的提示:遥感领域小样本语义分割
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (分类)KNN算法- 参数调优
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (函数)颠倒字符串顺序(C语言)
  • (四)opengl函数加载和错误处理
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (转)http协议
  • (转)Linux整合apache和tomcat构建Web服务器
  • (转)创业家杂志:UCWEB天使第一步
  • (转)关于pipe()的详细解析