【Cesium开发实战】飞行漫游功能的实现,可设置漫游路径,漫游高度,暂停,继续,删除路径
Cesium有很多很强大的功能,可以在地球上实现很多炫酷的3D效果。今天给大家分享一个可自定义的漫游飞行功能。
1.话不多说,先展示
漫游
(图片来源网络,侵删)
2.设计思路
项目需求,可自定义漫游路径,并且设置高度,暂停,继续,删除等功能。点击绘制开始在地图上绘制漫游的路径点位,双击结束后可编辑漫游路径名和漫游的高度设置。点击飞行,创建模型,使模型按照设定的点位和高度进行漫游。
3.具体代码
绘制 飞行 暂停 继续 确定 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 { // 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); } }); .page { position: absolute; right: 10px; top: 10px; color: #fff; background: #fff; padding: 10px; border-radius: 5px; width: 400px; }
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。