大小窗口画面切换

更新时间: 2024/09/18 16:26:13

移动 App 中 1 对 1 业务场景相应的音视频通话窗口的展现形式有两种,一种是 大屏幕视频(大窗口),一种是 悬浮窗视频(小窗口)

用户如果有需求,大屏幕视频和悬浮窗视频允许切换,可通过以下示例代码实现。

<!-- 固定大窗口 -->
<view class="nertc-video-area" :style="nertcRemoteViewStyle+'margin-top:-0rpx'">
	<view class="nertc-video-view" :style="nertcRemoteViewStyle" v-for="(item, index) in outterVideoList"
		:key="isShowUserScreenVideo ? item.key : item">
		<nertc-remote-view :style="nertcRemoteViewStyle" v-if="item" :mediaType="outterMediaType"
			:userID="isShowUserScreenVideo ? item.viewID : item"
			:viewID="isShowUserScreenVideo ? item.viewID : item">
		</nertc-remote-view>
	</view>
</view>


<!-- 悬浮窗 -->
<wrs-uts-floatPicInPicContainer v-if="floatWindowShow" ref='floatPicInPicContainer1'
	:style="`width: ${floatWindowSize.width}rpx;height: ${floatWindowSize.height}rpx;`">
	<wrs-uts-floatPicInPic ref='floatPicInPic1' @onLayouted="onLayouted">

		<view @tap="floatPicClick">
			<view class="nertc-video-area">
				<view class="nertc-video-view" v-for="(item, index) in floatWindowVideoList" :key="!isShowUserScreenVideo ? item.key : item">
					<nertc-remote-view
						:style="`width: ${floatWindowSize.width}rpx;height: ${floatWindowSize.height}rpx;flex: 1;margin-top:0`"
						v-if="item" :mediaType="floatWindowType" :userID="!isShowUserScreenVideo ? item.viewID : item" :viewID="!isShowUserScreenVideo ? item.viewID : item">
					</nertc-remote-view>
				</view>
			</view>
		</view>
	</wrs-uts-floatPicInPic>
</wrs-uts-floatPicInPicContainer>

	
	data: { 
		return {
			outterVideoList: [], //大屏幕视频
			outterMediaType: "subStreamVideo",
			floatWindowVideoList: [], //悬浮窗视频
			floatWindowType: "video",
		}
	}

//小窗的加载方法
async openPicInPic1() {
	let hasPermission = FloatPicInPic.canDrawOverlays();
	if (hasPermission) {
		this.floatWindowShow = true
		const that = this
		setTimeout(() => {

			let screenWidth = FloatPicInPic.getScreenWidth()
			let screenHeight = FloatPicInPic.getScreenHeight()
			// 宽度
			let width = screenWidth / 5
			// 高度
			let height = screenHeight / 5
			// X轴
			let x = screenWidth - width
			// Y轴
			let y = (screenHeight - height) - 30
			// 标签,用于后面小窗口删除、返回页面

			this.floatWindowSize = {
				width: width,
				height: height
			}
			let tag = 1
			this.$refs.floatPicInPic1.openPicInPic(x, y, width, height, tag)
			console.log("this.floatWindowSize: " + JSON.stringify(this.floatWindowSize));
			// this.$refs.floatPicInPicContainer1.setViewHidden(true)
		}, 1000);
	} else {
		let res = await util.showModal(myStr.getmyStr('m0000'), "当前没有悬浮窗权限,是否去打开权限?")

		if (!res.ok) {
			return;
		}
		FloatPicInPic.goToOpenOverlaysSetting()
	}
}


//小窗的点击方法
floatPicClick() {
	//麻烦在所有console输出日志的地方,都使用engine.nertcPrint接口多打印一遍,比如:
	// console.log('=====floatPicClick====');
	// engine.nertcPrint('=====floatPicClick===='),engine为SDK初始化的实例对象,这样=====floatPicClick====这个日志出了在控制台之外,也会写入app系统日志文件中了,调试会方便很多

	console.log('=====floatPicClick====');
	
	//1.5秒之内只能点击一次
	if (this.isTapBtn == true) {
		return;
	}
	this.isTapBtn = true
	setTimeout(() => {
		this.isTapBtn = false
	}, 1500)

	//2处理视频流
	this.isShowUserScreenVideo = !this.isShowUserScreenVideo
	
	//1、uniapp SDK内部是根据 nertc-remote-view 组件的生命周期来管理canvas画布的
	//2、destroyRemoteVideoCanvas仅仅是销毁画布和sdk之间的联系
	//3、因此业务上想变更画布,建议是先销毁nertc-remote-view组件,然后在创建nertc-remote-view
	
	if (this.isShowUserScreenVideo) {
		this.floatWindowType = 'video'
		//销毁悬浮窗视频的nertc-remote-view组件
		this.floatWindowVideoList = []
		this.$nextTick(() => {
			console.warn('此时远端视频 nertc-remote-view 销毁完成')
			//保证该组件销毁完成后,同步的执行后面的流程
			//清除音视频SDK内部绑定的view,之前对应的是视频辅流
			nertc.nertcUtils.destroyRemoteSubStreamVideoCanvas()
			
			//重新渲染nertc-remote-view组件
			this.floatWindowVideoList = this.remoteUserIdVideoList
			//保证当前nertc-remote-view组件渲染完成,然后执行设置画布的接口
			//否则可能会setupRemoteVideoCanvas时,由于此时页面上的nertc-remote-view组件还没有渲染
			//底层sdk根本找不到对应的view组件,因此setupRemoteVideoCanvas设置是失败的
			//如果不使用$nextTick方法,需要监听sdk的 onVideoCanvas 方法,需要在该方法中重新设置画布,可以参考云信官方文档中的示例代码
			this.$nextTick(() => {
				console.warn('此时远端视频 nertc-remote-view 渲染完成')
				//重新设置远端Video(即摄像头)的画布
				nertc.nertcUtils.setupRemoteVideoCanvas()
			})
		})
		
		this.outterMediaType = 'subStreamVideo'
		//销毁大屏幕视频的nertc-remote-view组件
		this.outterVideoList = []
		this.$nextTick(() => {
			console.warn('此时远端视频辅流 nertc-remote-view 销毁完成')
			//清除音视频SDK内部绑定的view,之前对应的是视频
			nertc.nertcUtils.destroyRemoteVideoCanvas()
			
			this.outterVideoList = this.remoteUserIDSubStreamVideoList
			this.$nextTick(() => {
				console.warn('此时远端视频辅流 nertc-remote-view 渲染完成')
				//重新设置远端subStramVideo(即屏幕共享)的画布
				nertc.nertcUtils.setupRemoteSubStreamVideoCanvas()
			})
		})
	} else {
		this.floatWindowType = 'subStreamVideo'
		
		//销毁悬浮窗视频的nertc-remote-view组件
		this.floatWindowVideoList = []
		this.$nextTick(() => {
			console.warn('此时远端视频 nertc-remote-view 销毁完成')
			//清除音视频SDK内部绑定的view,之前对应的是视频
			nertc.nertcUtils.destroyRemoteVideoCanvas()
			
			//重新渲染nertc-remote-view组件
			this.floatWindowVideoList = this.remoteUserIDSubStreamVideoList
			this.$nextTick(() => {
				console.warn('此时远端视频辅流 nertc-remote-view 渲染完成')
				//重新设置远端subStramVideo(即屏幕共享)的画布
				nertc.nertcUtils.setupRemoteSubStreamVideoCanvas()
			})
		})

		
		this.outterMediaType = 'video'
		
		//销毁大屏幕视频的nertc-remote-view组件
		this.outterVideoList = []
		this.$nextTick(() => {
			console.warn('此时远端视频辅流 nertc-remote-view 销毁完成')
			//清除音视频SDK内部绑定的view,之前对应的是视频辅流
			nertc.nertcUtils.destroyRemoteSubStreamVideoCanvas()
			
			this.outterVideoList = this.remoteUserIdVideoList
			this.$nextTick(() => {
				console.warn('此时远端视频 nertc-remote-view 渲染完成')
				//重新设置远端Video(即摄像头)的画布
				nertc.nertcUtils.setupRemoteVideoCanvas()
			})
		})
	}

	//不用设置定时器了,使用$nextTick方法等待nertc-remote-view渲染完成之后再设置画布
	/*
	setTimeout(() => {
		//3.1重新设置远端Video(即摄像头)的画布
		nertc.nertcUtils.setupRemoteVideoCanvas()
		//3.2重新设置远端subStramVideo(即屏幕共享)的画布
		nertc.nertcUtils.setupRemoteSubStreamVideoCanvas()
	}, 1000);
	*/
}
此文档是否对你有帮助?
有帮助
去反馈