uniapp 混合nvue开发上下切换视频(弃用)
vue使用原生子窗口实现视频上下切换
·
此文章存在挺多bug的,比如串音问题,黑屏问题,播放与暂停,占用内存过大,记录一下自己当前的开发思路
最初的构思开发:采用swiper上下切换
1.videoPlayer.nvue
<!-- videoPlayer.nvue -->
<template>
<view class="videoPlayer">
<video id="myVideo" class="video" :controls="false"
:src="'https://xiaoshipin.com/sipin/'+src" ref="myVideo" :loop="true"
:autoplay="false" @click="click"
object-fit="fill"
:enable-progress-gesture="false"
:show-fullscreen-btn="false"
:show-play-btn="false"
:show-center-play-btn="false"></video>
</view>
</template>
<script>
var timer = null
export default {
props: ['src', 'state'],
watch: {
state: {
immediate: true,
handler() {
this.stateChange();
}
}
},
data() {
return {
play: false,
dblClick: false,
};
},
mounted() {
},
methods: {
stateChange() {
let videos = this.$refs['myVideo'];
if (!!videos) {
let videoContext = videos;
switch (this.state) {
//视频播放
case 'play':
videoContext.play()
this.play = true
break;
//视频暂停
case 'pause':
videoContext.pause()
this.play = false
break;
//上下切换停止视频
case 'stop':
videoContext.pause(); //视频停止,从0开始
videoContext.seek(0);
this.play = false
break;
default:
break;
}
}
},
click() {
clearTimeout(timer)
this.dblClick = !this.dblClick
timer = setTimeout(() => {
if (this.dblClick) { //判断是单击 即为true
//单击
if (this.play === false) {
this.state = "play"
} else {
this.state = "pause"
}
} else {
//双击
this.$emit('dblClick') //向父组件传递一个事件
}
this.dblClick = false //点击后重置状态 重置为false
}, 300)
},
}
}
</script>
<style>
.videoPlayer {
flex: 1;
}
.video {
flex: 1;
}
</style>
2.subVideoList.nvue
<!-- subVideoList.nvue -->
<template>
<view class="page">
<swiper class="swiper" :circular="true" :vertical="true" @change="changeplay" >
<swiper-item class="swiper-item" v-for="item in videos" :key="item.id">
<view class="video" >
<video-player @dblClick='dblClick' :state="item.state" :src="item.src" >
</video-player>
</view>
</swiper-item>
</swiper>
</view>
</template>
<script>
import videoPlayer from './videoPlayer.nvue'
export default {
components: {
videoPlayer
},
data() {
return {
videos: [],
page: 0,
page_old: 0,
};
},
onLoad() {
uni.$on('sendSubVideoList', (data) => {
if (!!data) {
this.setState(this.page, 'play');
} else {
this.setState(this.page, 'pause');
}
})
},
onReady() {
this.videos = [{
src: '1.mp4',
state: 'pause'
}, {
src: '2.mp4',
state: 'pause'
}, {
src: '3.mp4',
state: 'pause'
}, {
src: '4.mp4',
state: 'pause'
}];
this.$nextTick(() => {
this.setState(this.page, 'play');
})
},
methods: {
dblClick() {
//双击点赞
},
changeplay(res) {
this.page = res.detail.current
this.setState(this.page_old, 'stop');
this.setState(this.page, 'play');
this.page_old = this.page;
},
setState(index, state_) {
let item = this.videos[index];
if (!!item) {
this.$set(this.videos, index, {
...item,
state: state_
});
}
},
}
}
</script>
<style>
.page {
flex: 1;
}
.swiper {
flex: 1;
}
.swiper-item {
flex: 1;
position: relative;
}
.video {
flex: 1;
/* #ifndef APP-PLUS */
width: 100%;
/* #endif */
}
</style>
3.创建video.vue,修改pages.json
{
"path": "pages/video/video",
"style": {
"navigationBarTitleText": "首页",
"app-plus": {
"titleNView": false,
"subNVues": [{
"id": "subVideoList", // 唯一标识
"path": "pages/video/subVideoList/subVideoList", // 页面路径
"style": {
"position": "absolute",
"top": "0",
"left": "0",
"width": "100%",
"height": "100%",
"mask": "rgba(0,0,0,0)",
"background": "rgba(0,0,0,0)",
"zindex": 5
}
}]
}
}
}
4.video.vue,使用subNVues显示原生子窗口
<template>
<view>
<!-- 其他内容 -->
</view>
</template>
<script>
let subVideoList = null;
export default {
data() {
return {
};
},
onReady() {
// #ifdef APP-PLUS
//通过 ID 获取 subNVues 原生子窗体的实例
subVideoList = uni.getSubNVueById('subVideoList');
//#endif
this.init();
},
onShow() {
if (!!subVideoList) {
subVideoList.show();
}
//界面显示继续播放
uni.$emit('sendSubVideoList', 1)
},
onHide() {
//界面隐藏停止播放
uni.$emit('sendSubVideoList', 0)
},
methods: {
init(){
if (!!subVideoList) {
subVideoList.show();
}
}
}
}
</script>
<style>
</style>
5.完成,不流畅,初始化显示还存在空白!不知道是不是渲染问题!!
6.最后还是决定使用list+@appear来实现,思路:cell高度为屏幕高度,使用@appear监听当前视频下标,通过下标来停止与播放视频,最后subVideoList.nvue如下
<!-- subVideoList.nvue -->
<template>
<view class="page">
<list @loadmore="loadmore" :loadmoreoffset="loadmoreoffset" :show-scrollbar="false" :pagingEnabled="true">
<cell v-for="(item, index) in videos" :key="index" :style="boxStyle" @appear="changeplay(index)">
<video-player @dblClick='dblClick' :state="item.state" :src="item.src">
</video-player>
</cell>
</list>
</view>
</template>
<script>
var deviceInfo = uni.getSystemInfoSync();
import videoPlayer from './videoPlayer.nvue'
export default {
components: {
videoPlayer
},
data() {
return {
loadmoreoffset: deviceInfo.windowHeight * 2, // 触发 loadmore 事件所需要的垂直偏移距离 加载到剩余2个的时候 继续加载
boxStyle: {
width: '750rpx',
height: deviceInfo.windowHeight + 'px'
},
videos: [],
page: 0,
page_old: 0,
};
},
onLoad() {
uni.$on('sendSubVideoList', (data) => {
if (!!data) {
this.setState(this.page, 'play');
} else {
this.setState(this.page, 'pause');
}
})
},
onReady() {
this.videos = [{
src: '1.mp4',
state: 'pause'
}, {
src: '2.mp4',
state: 'pause'
}, {
src: '3.mp4',
state: 'pause'
}, {
src: '4.mp4',
state: 'pause'
}];
this.$nextTick(() => {
this.setState(this.page, 'play');
})
},
methods: {
dblClick() {
},
loadMore(e) {
//加载更多的视频
this.videos.push({
src: 'new.mp4',
state: 'pause'
})
console.log('loadMore', e);
},
changeplay(index) {
this.page = index
this.setState(this.page_old, 'stop');
this.setState(this.page, 'play');
this.page_old = this.page;
},
setState(index, state_) {
let item = this.videos[index];
if (!!item) {
this.$set(this.videos, index, {
...item,
state: state_
});
}
},
}
}
</script>
<style>
.page {
flex: 1;
}
</style>
7.最终完成,上下切换流畅,测试100个视频也可以很流畅。
8.后期优化,数组动态加载与卸载,list组件缓存20个即可;点赞、评论、头像等使用cover-view覆盖在视频上面即可 ;page_old感觉很累赘,后期也删了
更多推荐
已为社区贡献3条内容
所有评论(0)