uni 中使用video在移动端层级过高问题解决方案

文章讲述了在项目中遇到的轮播图视频播放问题,包括层级过高导致显示异常、组件封装后API失效。作者介绍了四种解决方案,包括使用v-html处理层级、cover-view、子视图和popup弹窗,最终实现了跨平台兼容的视频播放控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题出现背景:

项目中的轮播图中包含图片和视频,点击视频进行视频播放

遇到了什么问题:

第一个问题:使用video标签控制视频播放,但在app中层级过高,显示出现问题

<video ref="videoId" id="videoId" 
:poster="_img.cover" :src="_img.path" 
v-if="_img.type == 2" style="width: 100%; height: 100%"
>
</video> -->

在这里插入图片描述

第二个问题:把轮播图封装在了组件中,video中的一些api比如暂停等全部失效了

change(e){
	uni.createVideoContext('videoId').pause();
},

swiper 中current 改变时会触发视频暂停,但是这里并没有生效

面临的这两个问题如何解决
首先层级问题,网上有很多种解决方法
总结一下目前使用比较多的有三种方法

方法一:使用vue中的v-html属性 设置innerHTML,内容中有html结构会被解析为标签。

<view class="" v-html="type1html"></view>
this.type1html=
`<video controls
id="videoId"
@play="play"
@fullscreenchange="fullscreenchange"
style="width:100%;height:auto;border-radius: 7px;object-fit: cover;position: absolute;top:30%;" poster="${items.cover?items.cover:'https://mp-ca8a1846-6eec-4662-aa41-add050d1945c.cdn.bspapp.com/static/icon/cover.png'}">
	<source src="${items.path}">
</video>`

通过控制自动全屏播放和退出全屏播放后暂停播放,来避免页面划走后视频仍旧播放的问题,但是,出现了封装在组件中的video 的api失效的问题

这时,我在组件中api使用时添加了this指向

uni.createVideoContext('videoId', this).pause();

依旧没有生效,并且安卓端甚至无法播放视频
ios端自动就开始进行视频全屏播放
存在严重的兼容性问题

方法二:在video标签中添加cover-view

首先什么是cover-view-子绝父相
在这里插入图片描述

<video ref="videoId" id="videoId" 
:poster="_img.cover" :src="_img.path" 
v-if="_img.type == 2" style="width: 100%; height: 100%"
>
	<cover-view style="width: 90vw; height: 55vh;background-color:#fff;"></cover-view>
</video>

效果并不好,因为是包在swiper里,swiper一滚动依旧是错乱的

方法三:subnvue 创建原生子窗体,放在当前页面下

onLoad() {
			const subNvue = uni.getSubNVueById('subNvue'); // 这个id是pages.json下绑定的唯一id
			// subNvue.hide();//标识初始隐藏

			subNvue.show('none', 0, () => {
				subNvue.setStyle({
					top: '90px',
					right: '20px',
					width: '90px',
					height: '114px'
				});
			});
 
		}
```html
<template>
	<view>
		<text style="font-size: 30px;color: #f00;">这是子窗体</text>
	</view>
</template>
 
<script>
	export default {
		data() {
			return {
				
			}
		},
		methods: {
			
		}
	}
</script>
 
<style>
 
</style>

这个方法可行,但是咱们是包在swiper里的,current发生改变的时候,子窗体会出现渲染延迟问题

第四个方法:迂回方法,我们在页面最上层加一个popup弹出层

弹出层就会整体覆盖在页面最上层,把video塞进popup中去,当点击遮罩关闭时暂停视频播放
我们把swiper里注入视频的封面图,给一个点击事件,点击打开弹出层自动开始播放视频
这样swiper无论如何都不会出错

<swiper indicator-active-color="#fff" class="" :current="current" indicator-dots @change="change" style="width: 90vw; height: 55vh;background-color: #1E1F24;border-radius: 32rpx;">
	<swiper-item v-for="(_img, index) in item.swiper" :key="index" style="border-radius: 32rpx; overflow: hidden;">
		<image v-if="_img.type===1" mode="aspectFit" :src="_img.path" style="width: 90vw; height: 55vh;"></image>
		<image v-if="_img.type===2" mode="aspectFit" :src="_img.cover" style="width: 90vw; height: 55vh;" @tap="showVideo(_img)"></image>
		<u-icon v-if="_img.type===2" name="play-right-fill" color="#fff" size="44" style="position: relative;top:-30vh;left:40vw;" @tap="showVideo(_img)"></u-icon>
	</swiper-item>
</swiper>

我们给swiper塞两个东西,一张普通的图片,一张视频的封面图,用返回类型来进行判断展示
再加一个弹框

<u-popup :show="video_show" :safeAreaInsetBottom="false" :safeAreaInsetTop="false" :closeable="true"
@close='close' mode="center">
<view style='width:100vw;height:40vh;'>
	<video :controls='true' style='width:100%;height:100%;' enable-			progress-gesture='false' direction='0'
		page-gesture="true" id="myVideo" autoplay='true'
		objectFit="contain" :src="videoUrl">
	</video>
</view>
</u-popup>

点击视频封面图展示弹框

showVideo(item){
	this.video_show = true
	this.videoUrl = item.path
	// 打开弹窗时开始视频播放
	uni.createVideoContext('myVideo', this).play()
},
close() {
	this.video_show = false
	// 关闭弹窗时暂停视频播放
	uni.createVideoContext('myVideo', this).pause()
},

三端一切正常
在这里插入图片描述

至此,问题解决

### uni-appvideo 组件层级问题解决方案 在开发过程中,`uni-app` 的 `video` 组件由于其默认渲染机制可能会导致层级,从而覆盖页面上的其他元素。要解决这一问题并实现视频上方叠加自定义元素的效果,可以采用以下方法: #### 方法一:通过设置 `z-index` 和 `position` 可以通过调整 CSS 样式中的 `z-index` 来控制层叠顺序。需要注意的是,`z-index` 只能作用于具有定位属性(如 `relative`, `absolute`, 或 `fixed`)的元素。 以下是具体实现方式: 1. 确保父容器设置了相对定位 (`position: relative`)。 2. 对需要叠加的子元素设置绝对定位 (`position: absolute`) 并赋予较的 `z-index` 值。 代码示例如下: ```html <view class="container"> <video id="myVideo" src="example.mp4"></video> <view class="overlay">叠加的内容</view> </view> ``` ```css .container { position: relative; } #myVideo { width: 100%; height: auto; } .overlay { position: absolute; top: 50px; /* 调整位置 */ left: 50px; /* 调整位置 */ background-color: rgba(255, 255, 255, 0.7); padding: 10px; z-index: 999; /* 设置优先级 */ } ``` 此方法的核心在于合理配置 `z-index` 和定位属性[^1]。 --- #### 方法二:引入 CSS Reset 或 Normalize.css 如果发现某些浏览器或平台存在样式差异,可能是因为不同环境下的默认样式未统一。此时可引入 `reset.css` 或 `normalize.css` 文件来消除这些差异。 对于 `uni-app` 开发者而言,推荐使用 `normalize.css`,因为它不仅清除了默认样式,还增强了跨浏览器一致性[^2]。 --- #### 方法三:动态绑定内联样式 当需要根据不同数据动态调整样式时,可以在模板中绑定变量作为内联样式的一部分。例如,在 `style` 属性中嵌入计算后的值。 代码示例如下: ```html <view :style="'--index:' + item.zIndex + '; --left:' + item.mLeft + 'px;'"> 动态内容 </view> ``` 这种方式特别适用于复杂场景下的布局需求[^3]。 --- ### 注意事项 - 如果上述方法仍无法解决问题,建议检查是否存在第三方插件或其他全局样式干扰。 - 需确认目标设备是否完全支持所使用的 CSS 特性,尤其是较老版本的 Android 浏览器可能存在兼容性问题---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值