Cesium添加图标后点击该图标出现弹窗的具体实现方法

实现效果:

点击左上角视频弹窗按钮,视角飞行,出现图标,并定位至指定位置;

点击图标,出现弹窗,弹窗可播放视频;

 

实现方法:

1.vue文件中:

template中:

<template>
	<div class="video_main">
        <!-- 左上角按钮 --!>
		<div class="switch_btn">
		 <el-button type="primary" @click="videoAddIcon()">视频弹窗(示例-宣传片)</el-button>
		</div>
		<!-- 视频弹窗 -->
		<div class="project-info" id="videoModel" ref="videoModel">
			<div class="project-info-top"></div>
			<div class="project-close" @click="closeInfo"></div>
			<div class="project-info-content">
				<video :src="videoUrl" controls class="video" width="100%"></video>
			</div>
		</div>
	</div>
</template>

script中:使用的方法从addVideo.js文件中引入

<script>
import { videoAddIconMarker, videoRemove, videoDialog, removeVideoDialog, setVideoHandler, removeHandler } from '@/earth/baseApp/addVideo.js'

export default {
	data() {
		return {
			videoUrl: 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4' // 视频播放测试链接
		}
	},
	beforeDestroy() {
		videoRemove() // 清除图标
		removeHandler() // 清除监听
	},
	methods: {
		// 添加图标
		videoAddIcon() {
			// 飞行位置
			viewer.camera.flyTo({
				destination: Cesium.Cartesian3.fromDegrees(116.609119, 40.080861, 106493.719)
			})
			// 调用监听方法
			videoAddIconMarker([116.609119, 40.080861], this.iconClickFunc)
			// 设置监听
			setVideoHandler()
		},
		// 点击弹窗样式
		iconClickFunc(entity) {
			// 调用点击出现弹窗方法
			videoDialog('videoModel', entity.position._value, 'Cartesian3')
		},
		// 关闭信息弹窗
		closeInfo() {
			// 调用关闭弹窗方法
			removeVideoDialog()
			this.videoUrl = '' // 清空数据 关闭视频播放
		},
		// 视频播放
		playVideo(row) {
			// 将接受的值赋值给src
			this.videoUrl = row.videoUrl
		}
	}
}
</script>

style中:

<style lang="scss" scoped>
.video_main {
	position: fixed;
	left: 330px;
	top: 125px;
	.switch_btn {
		position: absolute;
		top: 16px;
		left: 16px;
		display: flex;
	}
	// 弹窗样式:
	.project-info {
		width: 440px;
		height: 289px;
		background: rgba(0, 0, 0, 0.6);
		background-image: url('~@/assets/images/earthApp/messageBoxPop/righttwo.png') no-repeat;
		background-size: 100% 100%;
		position: fixed;
		z-index: 999;
		display: none;
		padding: 20px;
		box-sizing: border-box;
		.project-info-top {
			width: 377px;
			height: 5px;
			background: url('~@/assets/images/earthApp/messageBoxPop/liner.png') no-repeat;
			background-size: 100% 100%;
			color: #ffffff;
			font-size: 14px;
			font-family: Source Han Sans CN, Source Han Sans CN-Regular;
			font-weight: 400;
		}
		.project-close {
			width: 26px;
			height: 26px;
			position: absolute;
			top: 6px;
			right: 10px;
			background: url('~@/assets/images/earthApp/messageBoxPop/close.png') no-repeat;
			background-size: 100% 100%;
			cursor: pointer;
		}
		.project-info-content {
			width: 400px;
			// background: pink;
			margin-top: 20px;
			font-size: 14px;
			font-family: Source Han Sans CN, Source Han Sans CN-Regular;
			font-weight: 400;
			text-align: left;
			color: #cccccc;
			.project-info-inner-title {
				color: #ffffff;
				margin-top: -10px;
			}
			.project-info-inner {
				height: 16px;
				line-height: 16px;
				margin-top: 10px;
				// color: #ffffff;
				span:nth-child(2) {
					color: #ffffff;
				}
			}
			.project-info-pic {
				width: 100%;
				height: 80px;
				div {
					width: 128px;
					height: 80px;
					float: left;
					margin-top: 100px;
					margin-right: 5px;
					img {
						width: 129px;
						height: 80px;
					}
				}
			}
		}
	}
}
</style>

2.js文件中:

在js页面中设置全页面可用的数组:

let entArr = [] // 图标
let dialogBox = [] //点击图标出现的信息窗
let dialogBoxPreRenderListener = null; // cesium渲染监听
let handler = null // 鼠标左击事件监听

添加图标方法:

将新添加的图标放在了videoEntity中,方便后续使用,videoEntity存储着添加图标的所有内容。

position为地址,formDegrees为Cesium封装好的方法,参数为经度在前,纬度在后,传值时不能颠倒。

billboard为在地球上设置图标(广告牌)的相关设置,若图片地址为public下,可直接使用单引号引入,若在assets下,需使用require('')。

将添加的所有图标videoEntity统一存储在entArr数组中。

videoEntity.heightReference为图标相对于地形的位置,有3种:Cesium.HeightReference.CLAMP_TO_GROUND(该位置固定在地形上。)Cesium.HeightReference.NONE(该位置是绝对的。)

 Cesium.HeightReference.RELATIVE_TO_GROUND(位置高度是指地形上方的高度。)

clickFun为vue页面传递来的参数,将其绑定至监听鼠标点击事件的videoClick方法中,稍后介绍监听。

// 添加图标
function videoAddIconMarker(position, clickFunc) {
    let videoEntity = viewer.entities.add({
        id: 'videoModel',
        position: Cesium.Cartesian3.fromDegrees(position[0], position[1]),
        billboard: {
            // 图像地址,URI或Canvas的属性
            image: require('@/assets/images/earthApp/messageBoxPop/position.png'),
        }
    });
    entArr.push(videoEntity)
    videoEntity.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND;
    if (clickFunc) {
        videoEntity['videoClick'] = clickFunc;
    }
}

移除图标方法:

添加的所有图标videoEntity统一存储在entArr数组中,调用该方法时,若长度大于0,则使用remove移除图标。

将数组entArr清空,原因是:所有图标videoEntity统一存储在entArr数组中,当移除时仅移除了图标,并没有从数组中删除,故移除后清空数组。

// 移除所有图标
function videoRemove() {
    if (entArr.length > 0) {
        entArr.forEach((item) => {
            viewer.entities.remove(item)
        })
    }
    entArr = []; // 清空数组
}

点击图标添加信息窗方法:

videoBox为通过id(vue文件template中设置了)读取到的弹窗,读取到点击图标后其样式显示。

将弹窗内容video、弹窗位置videoPosition和弹窗类型videoType添加至dialogBox数组中存储。

进行Cesiun渲染监听(dialogBoxPreRenderListener )的判断 ,若为true则返回,否则进行渲染监听的设置:

首先添加监听并都存储在dialogBoxPreRenderListener中,对弹窗存储dialogBox进行遍历,设置其偏移高度和偏移宽度,然后对所传递来的位置类型进行判断,当为Cartesian3和LonLat分别采用不同的数值处理方式,最后通过对“左”和“上”的计算将其转化为在屏幕画布上的位置。

// 点击图标添加信息窗
function videoDialog(videoId, videoPosition, videoType) {
    const videoBox = document.getElementById(videoId);
    videoBox.style.display = 'block';
    dialogBox.push({
        video: videoBox,
        videoPosition: videoPosition,
        videoType: videoType
    })

    if (dialogBoxPreRenderListener) {
        return;
    } else {

        dialogBoxPreRenderListener = viewer.scene.preRender.addEventListener(function() {
            dialogBox.forEach(item => {
                let elWidth = item.video.offsetWidth - 700;
                let elHeight = item.video.offsetHeight - 70;
                const scratch = new Cesium.Cartesian2(); // cesium二维笛卡尔 笛卡尔二维坐标系就是我们熟知的而二维坐标系;三维也如此
                let position = null;
                if (item.videoType == 'Cartesian3') {
                    position = item.videoPosition;
                } else if (item.videoType == 'LonLat') {
                    position = Cesium.Cartesian3.fromDegrees(item.videoPosition[0], item.videoPosition[1], 20);
                }
                const canvasPosition = viewer.scene.cartesianToCanvasCoordinates(position, scratch);
                if (Cesium.defined(canvasPosition)) {
                    item.video.style.left = canvasPosition.x - elWidth / 2 + 'px';
                    item.video.style.top = canvasPosition.y - elHeight + 'px'
                }
            })
        })
    }
}

移除绑定到图标上弹窗的方法:

对存储弹窗的数组dialogBox进行判断,并进行遍历(因为考虑到不止一个弹窗的情况),使其展示样式不显示,同理将数组清空,进而将渲染监听清除。

// 移除绑定到图标上的弹窗
function removeVideoDialog() {
    if (dialogBox && dialogBox.length && dialogBox.length > 0) {
        dialogBox.forEach(item => {
            item.video.style.display = 'none';
        });
        dialogBox = [];
    }
    if (dialogBoxPreRenderListener) {
        dialogBoxPreRenderListener()
        dialogBoxPreRenderListener = null
    }
}

鼠标左击监听的方法:

设置监听方法将鼠标移动事件绑定至pickedObject中,对其进行判断,针对两种情况分别设置鼠标左击 的监听事件。

videoClick为一个方法,在添加图标(videoAddIconMarker)的方法中也调用了,此处为监听图标左击,若出现图标左击事件,则会传到vue文件中,调用其对应的相关方法。

// 监听
function setVideoHandler() {
    handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction(function(movement) {
        let pickedObject = viewer.scene.pick(movement.position);
        if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id) && typeof pickedObject.id.videoClick === 'function') {
            pickedObject.id.videoClick(pickedObject.id, movement);
        } else if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.primitive && typeof pickedObject.primitive.videoClick === 'function')) {
            pickedObject.primitive.videoClick(pickedObject, movement);
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}

移除监听:

在vue文件中调用,当图标移除时监听也随之消失;(ps:也可将该方法写在移除所有图标的方法中,就不用了导出写到vue中了)

/ 移除监听
function removeHandler() {
    if (handler) {
        handler.destroy();
        handler = null
    }
}

最后,将js文件中的所有方法导出,方便vue文件调用。

export { videoAddIconMarker, videoRemove, videoDialog, removeVideoDialog, setVideoHandler, removeHandler };

  • 3
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值