问题出现背景:
项目中的轮播图中包含图片和视频,点击视频进行视频播放
遇到了什么问题:
第一个问题:使用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()
},
三端一切正常
至此,问题解决