生成el-tree,勾选叶子节点后cesium在地球上同时添加多个图标,点击图标出现对应弹窗,与后端对接获取相应数据(并设置了只有叶子节点可以勾选)

实现目标:获取监控树,其中监控树只有叶子节点才有多选框,点击多选框在地球上添加多个图标,左击不同的图标出现对应的实时监控画面。监控树的数据以及实时监控的画面都是通过与后端对接接口获取的。

添加一个图标上图并点击出现弹窗可参考:Cesium添加图标后点击该图标出现弹窗的具体实现方法_刚刚好ā的博客-CSDN博客_cesium

同时添加多个图标的重点是:获取到数组后,将数组传递给cesium添加图标的方法,并对其进行处理,获取对应的经纬度,进而上图。

vue文件的template中:

监控树:

<div class="tree-con-tree">
					<el-tree
						:data="monitorTreeData"
						:props="defaultProps"
						show-checkbox
						node-key="name"
						:default-expand-all="false"
						:expand-on-click-node="false"
						ref="monitorTreeBox"
						@check-change="monitorTreeCheckedChange"
						:filter-node-method="filterNode"
					>
					</el-tree>
				</div>

视频为m3u8格式:具体的引入及播放可参考vue中播放m3u8格式实时监控画面(取流)--调用后端接口_刚刚好ā的博客-CSDN博客

<!-- 视频弹窗 -->
		<div class="project-info" id="videoModel" ref="videoModel">
			<div class="projtct-title">{{ monitorName }}</div>
			<div class="project-close" @click="closeInfo"></div>
			<div class="project-info-content">
				<div id="videobox"></div>
			</div>
		</div>

 vue文件的data中:

import { monitorTree, subMonitorPointPage, videoPreview } from '@/api/xx/xxxr'
import { videoAddIconMarker, videoRemove, videoDialog, removeVideoDialog, setVideoHandler } from '@/earth/xxxx/xxxx.js'
import videojs from 'video.js'
import 'videojs-contrib-hls'
data() {
		return {
			monitorTreeData: [], // 监控树
			defaultProps: {
				children: 'children',
				label: 'name',
				value: 'indexCode',
				emitPath: false,
				checkStrictly: true,
				expandTrigger: 'hover',
				disabled: 'disabled'
			},
			inputVal: '',
			latLonData: [], // 存放经纬度的数组
			indexCodeCamera: '', // 子节点id
			srcPath: '', // 视频播放链接
			monitorName: '' // 监控点名称
		}
	},

在data之前定义这两变量,方便后面的使用 

let myVideo = null
let entVideo = null

vue文件的mouted:初始该界面时就加载监控树

mounted() {
		this.getMonitorTree()
	},

vue文件的watch:

watch: {
		// 取消勾选时移除图标
	beforeDestroy() {
		videoRemove() // 清除图标
	},

vue文件的methods中:

获取监控树,设置只有叶子节点可勾选

// 获取监控树
		getMonitorTree() {
			monitorTree().then((res) => {
				if (res.status == 200) {
					this.setMonitorData(res.data.data.children[0].children)
				} else {
					this.$message.warning('请稍后再试')
				}
			})
		},
		// 设置只有叶子结点可勾选
		setMonitorData(data) {
			let nowdata = data
			nowdata.forEach((item) => {
				setData(item)
			})
			this.monitorTreeData = nowdata
			function setData(data) {
				if (data.children.length == 0) {
					data.disabled = false
				} else {
					data.disabled = true
					data.children.forEach((item) => {
						setData(item)
					})
				}
			}
		},

勾选多选框图层改变:

videoAddIconMarker为添加多个图标的方法,此时将获取的数组进行传递,方便在js文件中的此方法获取到相应的经纬度。同时设置监听,来监控鼠标左击的变化。

monitorTreeCheckedChange(data, checked) {
			if (checked) {
				if (data) {
					// 最终一层节点数据获取--数据格式为表单
					let monitorForm = new FormData()
					monitorForm.append('regionIndexCode', data.indexCode)
					monitorForm.append('treeCode', 0)
					monitorForm.append('pageNo', 1)
					monitorForm.append('pageSize', 1000)
					// 调用接口--获取叶子节点的数据
					subMonitorPointPage(monitorForm).then((res) => {
						if (res.status == 200) {
							let newArr = res.data.data.list
							videoAddIconMarker(newArr, this.iconClickFunc)
						} else {
							this.$message.warning('请稍后再试')
						}
					})
				} else {
					this.monitorData = []
				}
				// // 设置监听
				setVideoHandler()
			} else {
				videoRemove()
				this.closeInfo()
			}
		},

点击出现弹窗:

// 点击弹窗样式
		iconClickFunc(entity) {
			// 调用点击出现弹窗方法
			// console.log(entity)
			if (entVideo && entity.id == entVideo.id) {
				this.closeInfo()
			} else {
				if (entity) {
					entVideo = entity
					entVideo.billboard.image = require('@/assets/images/xxxx.png')
				}
				// 修改实体样式
				this.showVideoDiv(entity.id, entity.name, entity.position._value)
			}
		},

视频弹窗:

// 视频弹窗显示
		showVideoDiv(id, name, position) {
			//动态生成video
			let doc = document.getElementById('videobox')
			let dd = document.createElement('div')
			dd.innerHTML = `<video
            id="myVideoPlay"
            class="video-js vjs-default-skin vjs-big-play-centered"
            controls
            preload="auto"
            width="388"
            height="189"
            data-setup="{}"
          ></video>`
			doc.appendChild(dd)
			this.monitorName = name
			this.srcPath = ''
			this.indexCodeCamera = id
			let param = {
				cameraIndexCode: this.indexCodeCamera
			}
			// 获取摄影监控实时画面
			videoPreview(param).then((res) => {
				if (res.status == 200) {
					this.srcPath = res.data.data.url
					console.log(this.srcPath)
					setTimeout(() => {
						if (myVideo) {
							myVideo.dispose()
							myVideo = null
						}
						myVideo = videojs('myVideoPlay', {
							bigPlayButton: true,
							textTrackDisplay: false,
							posterImage: false,
							errorDisplay: false
						})
						myVideo.src(this.srcPath)
						myVideo.play()

						// myVideo.pause();
					})
				} else {
					this.$message.warning('请稍后再试')
				}
				videoDialog('videoModel', position, 'Cartesian3')
			})
		},
		// 关闭信息弹窗
		closeInfo() {
			if (myVideo) {
				myVideo.dispose()
				myVideo = null
			}
			if (entVideo) {
				entVideo.billboard.image = require('@/assets/images/xxx.png')
				entVideo = null
			}
			// 调用关闭弹窗方法
			removeVideoDialog()
		},
		// 视频播放
		playVideo(row) {
			// 将接受的值赋值给src
			this.videoUrl = row.videoUrl
		}
	}

添加图标的js文件中:

添加图标的方法是重点,这里将传递来的数组进行遍历,获取其对应的经纬度。

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

// 添加图标
function videoAddIconMarker (arr, clickFunc) {
	arr.forEach(item => {
		if (item.longitude > 0 && item.latitude > 0) {
			let videoEntity = viewer.entities.add({
				id: item.cameraIndexCode,
				name: item.name,
				position: Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude),
				billboard: {
					// 图像地址,URI或Canvas的属性
					image: require('@/assets/images/xxxx.png'),
					width: 50,
					height: 50,
					heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
				}
			});
			entArr.push(videoEntity)
			if (clickFunc) {
				videoEntity['videoClick'] = clickFunc;
			}
		}

	})

}

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

// 点击图标添加信息窗
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();
				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'
				}
			})
		})
	}
}

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

// 设置监听
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);
}

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

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

接口js文件:

// 查询摄像监控树
export function monitorTree (param) {
	return request({
		url: "/xxx/monitorTree",
		method: "post",
		headers: {
			"Content-Type": "application/json" // 如果写成contentType会报错
		},
		data: param
	});
}

// 获取叶子节点数据
export function subMonitorPointPage (param) {
	return request({
		url: "/xxxx/subMonitoringPoint",
		method: "post",
		data: param
	});
}

// 取流 ==> 视频应用服务--获取监控点预览取流URL
export function videoPreview (param) {
	return request({
		url: "/xxxx/videoPreview",
		method: "post",
		data: param
	});
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Cesium 上渲染大量的图标时,可以采用以下最佳实践来提高性能: 1. 使用 Cesium BillboardCollection 对象:Cesium BillboardCollection 对象是一种专门用于渲染大量图标的对象,可以大幅提高性能。可以使用以下代码创建 BillboardCollection 对象: ``` var billboardCollection = new Cesium.BillboardCollection(); scene.primitives.add(billboardCollection); ``` 2. 使用 Cesium.TextureAtlas 对象:Cesium.TextureAtlas 对象可以将多个图标合并到一个纹理中,从而减少纹理切换的次数,提高性能。可以使用以下代码创建 TextureAtlas 对象: ``` var textureAtlas = new Cesium.TextureAtlas({ scene: scene, imageSize: new Cesium.Cartesian2(2048, 2048) }); ``` 3. 使用 Cesium.PinBuilder 对象:Cesium.PinBuilder 对象可以快速创建各种类型的图标,包括纯色、带文字、带图片等等。可以使用以下代码创建 PinBuilder 对象: ``` var pinBuilder = new Cesium.PinBuilder(); ``` 4. 使用 Cesium.Billboard 对象:Cesium.Billboard 对象用于表示一个图标,可以设置图标的位置、大小、旋转角度、纹理等属性。可以使用以下代码创建 Billboard 对象: ``` var billboard = billboardCollection.add({ position: Cesium.Cartesian3.fromDegrees(lon, lat), image: textureAtlas.getTexture({ index: textureIndex }), width: size, height: size, rotation: angle }); ``` 5. 批量添加图标:为了提高性能,可以批量添加图标,而不是逐个添加。可以使用以下代码批量添加图标: ``` var billboards = []; for (var i = 0; i < count; i++) { var billboard = { position: Cesium.Cartesian3.fromDegrees(lon, lat), image: textureAtlas.getTexture({ index: textureIndex }), width: size, height: size, rotation: angle }; billboards.push(billboard); } billboardCollection.add(billboards); ``` 需要注意的是,以上代码仅供参考,具体实现需要根据实际需求进行调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值