思路
主要是用到uniapp官网的swiper
组件 然后再嵌套一个video
组件,下面是我的实现效果:
问题
当我使用官方的autoplay
属性实现自动播放,会导致我切换下一个视频的时候出现声音播放还停留在上一个视频,或者多个视频的声音同时播放。
实现
一开始是拿到所有视频的数据,根据点击的当前视频对象中的id
获得swiper
需要的current
(就是当前下标),正确定位到当前点击的视频,然后自己去控制自动播放视频
注意
这个地方是没有手动关闭的,所以就肯定会导致我上面所说的那种画面变了但是声音还停留在上一个视频的问题,这是最主要的swiper
的两个事件
这里的('id' + this.current)
就是对应上面的:id="'id'+index"
目的是为了动态的监听id
的值 实现播放和暂停播放,要注意 this.current
和current
所有的代码还有数据格式(有用的值就这四个)
所有代码
<template>
<view>
<view class="uni-padding-wrap">
<view class="page-section swiper">
<view class="page-section-spacing">
<swiper class="swiper" @change="changefun" @animationfinish="animationfinishfun" :current="current" :circular="false" :vertical="true">
<block v-if="PayVideo">
<swiper-item v-for="(item,index) in PayVideo">
<view class="swiper-item uni-bg-black">
<video
:custom-cache="false"
:show-fullscreen-btn="false"
:controls="true"
:show-center-play-btn="false"
enable-play-gesture
:initial-time="0"
class="video"
:id="'id'+index"
:src="item.video_url"
loop
:enable-progress-gesture="false"
v-if="index == current"
>
</video>
</view>
</swiper-item>
</block>
</swiper>
</view>
</view>
</view>
<view>
<view class="left">
<cover-view class="left_box">
<cover-view class="ke_context height">{{description}}</cover-view>
<!-- <cover-view class="auto">
<cover-view>视频总时长:{{duration || 0}}</cover-view>
</cover-view> -->
</cover-view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
PayVideo: [],
videoData: {},
videoList: [],
description: '',
current: 0,
index_: 0,
videoContext: '',
duration: '',//总视频时长
}
},
computed: {
},
onLoad(options) {
this.getVideoInfo(parseInt(options.id))
if(options.videoList) {
this.videoList = JSON.parse(decodeURIComponent(options.videoList))
}
},
methods: {
getVideoInfo(id){
this.$http.get('/video/detail',{
video_id:id
}).then(res=>{
if(res.code==0){
this.videoData = res.data;
this.id = res.data.id
uni.setNavigationBarTitle({
title:this.videoData.video_name
})
this.description = this.videoData.description
this.PayVideo = this.videoList //上下滑动总数据
this.current = this.PayVideo.findIndex((item) => {
return item.id === res.data.id
})
this.duration = res.data.video_time
// 自动播放当前视频
this.$nextTick(function() {
let videoContext = uni.createVideoContext('id' + this.current)
videoContext.play()
})
}else{
uni.showToast({
title:res.msg,
icon:'none'
})
setTimeout(()=>{
uni.redirectTo({
url:'/pages/index/index?index=2'
})
},1500)
}
})
},
// current改变时会触发change 事件
changefun(e) {
let current = e.detail.current
uni.setNavigationBarTitle({
title: this.PayVideo[current].video_name
})
if(this.PayVideo[current].description) {
this.description = this.PayVideo[current].description
}
this.duration = this.PayVideo[current].video_time
let videoContext = uni.createVideoContext('id' + this.current)
videoContext.pause() //停止播放
},
// 动画结束时触发
animationfinishfun(e) {
let current = e.detail.current
let videoContext = uni.createVideoContext('id' + this.current)
videoContext.pause() //停止播放非当前视频
videoContext = uni.createVideoContext('id' + current)
videoContext.play() //开始播放当前视频
this.current = current //保存当前下标 播放下一个视频时停止上一个视频 防止声音重复
}
},
}
</script>
<style scoped lang="less">
.circle {
background: rgba(34, 34, 34, 0.4);
border-radius: 50%;
z-index: 2;
height: 70px;
width: 70px;
position: fixed;
top: 0;
bottom: 441rpx;
left: 31rpx;
margin: auto;
.red {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
z-index: 3;
height: 35px;
width: 35px;
}
}
.swiper {
height: 100vh;
.swiper-item {
height: 100vh;
position: relative;
}
.uni-bg-black {
background: black;
}
}
.video {
width: 100%;
height: 98vh;
position: relative;
}
.left_box {
position: fixed;
bottom: 90rpx;
left: 24rpx;
.ke_context {
overflow-y: scroll;
max-height: 300rpx;
white-space:pre-wrap;
width: 700rpx;
font-size: 30rpx;
font-family: PingFang SC;
font-weight: 500;
color: rgba(255, 255, 255, 1);
white-space:pre-wrap;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.4);
}
.height {
margin-bottom: 40rpx;
}
.ren {
margin: 20rpx 0;
font-size: 36rpx;
font-family: PingFang SC;
font-weight: bold;
color: rgba(255, 255, 255, 1);
text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.4);
}
.auto {
display: flex;
align-items: center;
width: 310rpx;
height: 60rpx;
margin-top: 24rpx;
opacity: 1;
border-radius: 8rpx;
padding-left: 10rpx;
cover-view {
font-size: 26rpx;
font-family: PingFang SC;
font-weight: 500;
color: rgba(255, 255, 255, 1);
line-height: 90px;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.4);
}
cover-image {
margin-right: 10rpx;
height: 28rpx;
width: 26rpx;
}
}
.ke {
display: flex;
align-items: center;
width: 310rpx;
height: 60rpx;
background: rgba(0, 0, 0, 0.3);
opacity: 1;
border-radius: 8rpx;
padding-left: 10rpx;
cover-view {
font-size: 26rpx;
font-family: PingFang SC;
font-weight: 500;
color: rgba(255, 255, 255, 1);
line-height: 90px;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.4);
}
cover-image {
margin-right: 10rpx;
height: 40rpx;
width: 40rpx;
}
}
}
.H_T {
z-index: 2;
width: 100%;
display: flex;
box-sizing: border-box;
position: absolute;
padding: 0 30rpx;
background: transparent;
justify-content: space-between;
.back {
height: 48rpx;
width: 48rpx;
}
.search {
height: 48rpx;
width: 48rpx;
}
}
.right_box {
width: 100rpx;
position: absolute;
z-index: 2;
bottom: 60rpx;
right: 12rpx;
display: flex;
flex-direction: column;
.top1 {
position: relative;
height: 124rpx;
.avatar_img {
width: 98rpx;
height: 98rpx;
border-radius: 50%;
}
.add_img {
position: absolute;
z-index: 99;
width: 48rpx;
height: 48rpx;
bottom: 10rpx;
left: 0;
right: 0;
margin: 0 auto;
}
}
.top2 {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 37rpx;
.t_img {
height: 72rpx;
width: 72rpx;
margin-bottom: 10rpx;
}
.font_t {
font-size: 26rpx;
font-family: SF Pro Text;
font-weight: 500;
color: rgba(255, 255, 255, 1);
text-shadow: 0px 1rpx 1rpx rgba(0, 0, 0, 0.4);
text-align: center;
}
}
}
</style>