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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/45527.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何制作文件的二维码?支持设置文件下载功能

现在为了能够更快的将文件分享给其他人查看&#xff0c;会选择将文件转换二维码的方式&#xff0c;用户可以通过扫描二维码在手机上预览或者下载文件到本地&#xff0c;能够有效的减少文件对内存的占用&#xff0c;在很多场景下都有所应用&#xff0c;那么文件转二维码具体该怎…

TCP/IP模型和OSI模型的区别(面试题)

OSI模型&#xff0c;是国际标准化组织ISO制定的用于计算机或通讯系统间互联的标准化体系&#xff0c;主要分为7个层级&#xff1a; 物理层数据链路层网络层传输层会话层表示层应用层 虽然OSI模型在理论上更全面&#xff0c;但是在实际网络通讯中&#xff0c;TCP/IP模型更加实…

LabVIEW电子水泵性能测试平台

开发了一种车用电子水泵性能测试平台&#xff0c;该平台以工控机为载体&#xff0c;利用LabVIEW开发上位机软件&#xff0c;采用PLC控制阀门和水泵等电气元件&#xff0c;通过RS485进行数据采集并传输到上位机。通过上位机与下位机的协同控制&#xff0c;实现了数据交互处理和性…

LeetCode题练习与总结:寻找旋转排序数组中的最小值Ⅱ--154

一、题目描述 已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,4,4,5,6,7] 在变化后可能得到&#xff1a; 若旋转 4 次&#xff0c;则可以得到 [4,5,6,7,0,1,4]若旋转 …

基于Java Web的考编论坛网站的设计与实现+lw+源码+讲解+调试+视频演示

第3章 系统分析 用户的需求以及与本系统相似的在市场上存在的其它系统可以作为系统分析中参考的资料&#xff0c;分析人员可以根据这些信息确定出本系统具备的功能&#xff0c;分析出本系统具备的性能等内容。 3.1可行性分析 尽管系统是根据用户的要求进行制作&#xff0c;但…

聚鼎贸易:装饰画生意能不能做起来2024

在2024年&#xff0c;随着人们对家居美学和个性化表达的需求日益增长&#xff0c;装饰画作为一种简单而直接的方式&#xff0c;来提升空间品味及展示个人风格的市场需求也随之扩大。许多人都对涉足这一行业抱有浓厚的兴趣&#xff0c;但究竟这门生意能否成功做大&#xff0c;需…

Unity 资源 之 战斗魔法咒语 - 第二卷(Combat Magic Spells - Volume II)

&#x1f389;Unity Asset Store 宝藏免费资源&#xff1a;战斗魔法咒语 - 第二卷 前言资源包内容领取兑换码 前言 各位游戏开发爱好者、Unity 开发者们&#xff0c;今天要给大家带来一个超棒的消息&#xff01;在 Unity Asset Store 上&#xff0c;全新的免费资源“战斗魔法咒…

Java高级重点知识点-27-Java反射机制

文章目录 Java反射机制概述理解Class类并获取Class的实例Class 类 类的加载与ClassLoader类加载过程类的初始化触发条件类加载器的作用ClassLoader 创建运行时类的对象获取运行时类的完整结构调用运行时类的指定结构反射的应用&#xff1a;动态代理Proxy类AOP&#xff08;Aspec…

JavaWeb系列二十一: 数据交换和异步请求(JSON, Ajax)

文章目录 官方文档official documents官方文件官方文件official documentsJSON介绍JSON快速入门JSON对象和字符串对象转换应用案例注意事项和细节 JSON在java中使用说明JSON在Java中应用场景应用实例 Ajax基本介绍Ajax是什么Ajax经典应用场景 Ajax原理示意图传统的web应用Ajax原…

Vue3打包发布,刷新出现的空白页面和错误

Vue3打包发布出现的错误&#xff1a;Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of text/html. Strict MIME type checking is enforced for module scripts per HTML spec. 第一次点击访问到这个路径&…

粉笔推出国内首个职教行业大模型,助力学员高效学习

7月12日&#xff0c;粉笔正式推出其自主研发的首个专注于职教行业的垂域大模型&#xff0c;并将于8月1日上线粉笔AI老师 “粉笔头”&#xff0c;为学员提供个性化、智能化的辅导服务。 在垂域大模型的基础上&#xff0c;粉笔结合10年来的教研积累、独有数据搭建RAG系统&#x…

java上手

java上手 文章目录 java上手0.注释1.简单的输出2.从控制台读取输入3.标识符4.变量5.赋值6.常量7.命名习惯 0.注释 // 单行注释 /*多行注释*/ /**对类和方法进行说明*/1.简单的输出 public class HelloWorld{public static void main(String[] args){System.out.println("…

使用MAVSDK向PX4模拟器发送启飞与降落指令

1.使用docker启动PX4模拟器 docker run --rm -it jonasvautherin/px4-gazebo-headless:1.14.3 开始启动 启动中 PX4启动成功 创建QGC连接 mavlink start -p -u 14556 -t 192.168.1.66 -o 14550 启动QGC连接PX4模拟器 在QGC中执行各种指令

TensorFlow系列:第五讲:移动端部署模型

项目地址&#xff1a;https://github.com/LionJackson/imageClassification Flutter项目地址&#xff1a;https://github.com/LionJackson/flutter_image 一. 模型转换 编写tflite模型工具类&#xff1a; import osimport PIL import tensorflow as tf import keras import …

电子画册制作全攻略,从零开始制作

在这个数字化时代&#xff0c;电子画册作为一种新型的传播媒介&#xff0c;已经越来越受到人们的青睐。它以生动活泼、互动性强、传播速度快等特点&#xff0c;迅速成为了企业宣传、个人展示的优质选择。那么&#xff0c;如何从零开始制作一款引人入胜的电子画册呢&#xff1f;…

pdf文件如何快速英文转中文?

要将 PDF 文件中的英文内容转换为中文&#xff0c;你可以使用以下几种方法&#xff1a; 1、在线翻译工具&#xff1a; 使用网上的免费在线翻译工具&#xff0c;如Google翻译、百度翻译或有道翻译&#xff0c;将整个 PDF 文档粘贴到工具中进行翻译。 2、专业翻译软件&#xf…

数据结构——(双)链表

文章目录 1. 定义 2. 双链表和单链表的区别 3. 代码示例 3.1 双链表节点和结构定义 3.2 初始化双链表 3.3 返回双链表的长度 3.4 在指定位置插入元素 3.5 在末尾插入元素 3.6 删除指定位置的元素并返回被删除的元素 3.7 删除末尾元素 3.8 获取指定位置的元素 3.9 修…

笔记:使用Microsoft.EntityFrameworkCore.Proxies做数据库延迟加载

一、目的&#xff1a; Microsoft.EntityFrameworkCore.Proxies 是一个Entity Framework Core的扩展包&#xff0c;它提供了对延迟加载的支持。延迟加载是一种ORM&#xff08;对象关系映射&#xff09;行为&#xff0c;允许在首次访问导航属性时&#xff0c;自动从数据库加载相关…

面向对象进阶基础练习

Java学习笔记&#xff08;新手纯小白向&#xff09; 第一章 JAVA基础概念 第二章 JAVA安装和环境配置 第三章 IntelliJ IDEA安装 第四章 运算符 第五章 运算符联系 第六章 判断与循环 第七章 判断与循环练习 第八章 循环高级综合 第九章 数组介绍及其内存图 第十章 数…

AI网络爬虫019:搜狗图片的时间戳反爬虫应对策略

文章目录 一、介绍二、输入内容三、输出内容一、介绍 如何批量爬取下载搜狗图片搜索结果页面的图片?以孙允珠这个关键词的搜索结果为例: https://pic.sogou.com/pics? 翻页规律如下: https://pic.sogou.com/napi/pc/searchList?mode=2&start=384&xml_len=48&am…