接口是在其它csdn文章中找的
首先实现上下滑动的基本功能
然后再添加暂停播放功能
最后添加自定义slier进度条,通过点击或拖拽进度条进入到视频对应的时间位置
功能要素如下:
完整代码:
<template>
<view class="">
<swiper class="swiper" :style="{height:screenHeight+'px'}" :vertical="true" :duration="1000"
@transition="transition" @change="changed">
<swiper-item class="swiper-item" :style="{height:screenHeight+'px'}" v-for="(item,index) in videoList"
:key="index" >
<!-- 11111{{index==changeIndex}} -->
<video id="myVideo" class="playVideo" :style="{height:screenHeight+'px'}" object-fit="cover" autoplay
:src="item.src" :controls="false" @tap="handleVideoTap" loop @timeupdate="onTimeUpdate($event)"
@loadeddata="onVideoLoadedData(index)" @play="onVideoPlay" v-if="index==changeIndex||showFlag">
</video>
<!-- <image v-else class="fmBox" :src="item.fmsrc" mode="aspectFill"></image> -->
<view class="txtWrap">
<text class="nickname" style="color: #fff;font-size: 18px;">
@Picnic熊
</text>
<text class="tit"
style="width:500rpx;color: #fff;font-size: 14px;text-overflow: ellipsis; lines:2;">
{{item.title}}
</text>
</view>
</swiper-item>
</swiper>
<view class="iconWrap" :style="{height:screenHeight+'px'}">
<image class="playIcon" src="/static/play.png" style="" v-if="!playFlag"></image>
<view class="control_box">
<slider class="sliderbox" :value="currentProgress" min="0" @change="sliderChange"
@changing="sliderChanging" max="100" activeColor=" #6d6d6d" backgroundColor="#2f2f2f"
block-color="#6d6d6d" block-size="12" />
</view>
<view class="changing" v-if="showChanging">
<text style="color: #fff;font-size: 20px;">{{sliderchanging}}</text>
<text style="color: #c5c5c5;font-size: 20px;">/ {{totalDuration}}</text>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
screenHeight: 0,
originList: [], // 源数据
displaySwiperList: [], // swiper需要的数据
displayIndex: 0, // 用于显示swiper的真正的下标数值只有:0,1,2。
originIndex: 0, // 记录源数据的下标
changeIndex: 0, //控制video是否渲染
page: 0, // 视频分页
num: 0,
flag: true,
showFlag:false,
videoList: [{
"src": "https://minivideo.xiu123.cn/original/79649956972748019fb7761c6852c5b1/25d3d19-17b2a2529da.mp4",
"title": "……… 时过尽迁!",
"fmsrc": "../../static/fm1.png"
},
{
"src": "https://minivideo.xiu123.cn/original/6b474d2596d742ab8f1c1da42145ee4d/5a8969da-17afdba394d.mp4",
"title": "完美收官/美女/靓仔",
"fmsrc": "../../static/fm2.png"
},
{
"src": "https://minivideo.xiu123.cn/original/95267608f6c94ec786bf2799add0aa7a/d5538f3-17b49507b12.mp4",
"title": "人生不过如此,且行且珍惜。",
"fmsrc": "../../static/fm.png"
},
{
"src": "https://minivideo.xiu123.cn/original/e09a1efc53304a30b14258c9f81c53d3/2ca04e20-17b4ad28fe4.mp4",
"title": "皮一下🤪🤪🤪",
"fmsrc": "../../static/fm1.png"
},
{
"src": "https://minivideo.xiu123.cn/original/41ce5089729b42388d8beeebffa3b0ea/1896b231-17ea06304eb.mp4",
"title": "❤️🧡💛💚💙💜接受自",
"fmsrc": "../../static/fm2.png"
},
{
"src": "https://minivideo.xiu123.cn/original/9866913b960b48aea4ba9795e438e105/324d23bd-17ea0807e3e.mp4",
"title": "本年度最后一场正式直",
"fmsrc": "../../static/fm.png"
},
{
"src": "https://minivideo.xiu123.cn/original/1177f5d195d44404991943fc2ee6afb5/58469ddf-17ea1339711.mp4",
"title": "555",
"fmsrc": "../../static/fm1.png"
},
{
"src": "https://minivideo.xiu123.cn/original/227284517d2a4858bfe36194106f3978/138a8ce0-17ea2217e0b.mp4",
"title": "村上树说“你要记得那",
"fmsrc": "../../static/fm2.png"
},
{
"src": "https://minivideo.xiu123.cn/original/b63ba4528456418f9ded1fb9a568e0ca/3c42538d-17ea016eeb0.mp4",
"title": "回村过大年了,家人们",
"fmsrc": "../../static/fm.png"
},
{
"src": "https://minivideo.xiu123.cn/original/9fe073c59b25443fa424a920238d186c/1e9e041d-17d71e53bd0.mp4",
"title": "最后一个月啦/狂笑",
"fmsrc": "../../static/fm1.png"
}
],
videoContext: null,
playFlag: true,
currentProgress: 0, // 当前播放进度
totalDuration: "00:00", // 视频总时长
playTime: "00:00",
videoPrecent: 0,
sliderallTime: 0,
precenting: 0,
sliderchanging: "00:00",
timerclear: false,
showChanging: false, //控制定时器和changing的显示
// sliderTimer: null, //定时器
pageStartY: 0,
pageEndY: 0,
}
},
computed: {
canCircular() {
// return (this.originIndex + 1 == this.originList.length ? 0 : this.originIndex + 1) == 1;
}
},
onLoad() {
/* 获取系统信息 */
uni.getSystemInfo({
success: (res) => {
this.screenHeight = res.windowHeight
}
});
// 调用函数
this.getPageID()
},
onReady: function(res) {
this.videoContext = uni.createVideoContext('myVideo')
},
methods: {
transition(e) {
// let originListLength = this.originList.length;
// if ((this.originIndex + 1 == originListLength ? 0 : this.originIndex + 1) == 1 && e.detail.dy < -100) {
// uni.showToast({
// title: '已经到顶了',
// icon: 'none'
// })
// }
},
/* 生成随机的 pageID */
getPageID() {
// console.log("getPageID")
let pageID = parseInt(Math.random() * (0 - 100 + 1) + 100) //生成 [min,max] 的随机数
this.getVideoList(pageID)
},
/* 获取视频数据 */
getVideoList(pageID) {
uni.request({
url: 'https://api.apiopen.top/api/getMiniVideo?page=' + pageID +
'&size=10&pageSize=10', // 请求数据接口
data: {},
success: (res) => {
if (res.data.code == 200) {
res.data.result.list.forEach(item => {
//取源数据的部分属性组合成新的数组
let obj = {}
obj.src = item.playurl
obj.title = item.title
this.originList.push(obj)
})
}
}
})
},
changed(event) {
this.currentProgress = 0;
this.playFlag = true
let {
current
} = event.detail;
this.changeIndex = current;
// console.log(event)
let f1 = this.originList.length - 1
if ((current + 1) >= this.originList.length) {
console.log("到底")
this.getPageID()
}
},
handleVideoTap(e) {
// console.log("hang")
// this.videoContext.pause();
if (this.playFlag) {
this.videoContext.pause();
this.playFlag = false
} else {
this.videoContext.play();
this.playFlag = true
}
},
onTimeUpdate(e) {
let playTime = e.detail.currentTime
this.sliderallTime = e.detail.duration
this.playTime = this.formatSecondsToMMSS(Math.floor(playTime));
this.totalDuration = this.formatSecondsToMMSS(Math.floor(this.sliderallTime));
if (this.timerclear) {
// clearTimeout(this.sliderTimer)
// this.sliderTimer = null
this.showChanging = false
this.timerclear = false
return
}
// this.sliderTimer = setTimeout(() => {
// })
this.currentProgress = playTime / this.sliderallTime * 100;
},
formatSecondsToMMSS(seconds) {
let minutes = Math.floor(seconds / 60);
let remainingSeconds = seconds % 60;
minutes = ('0' + minutes).slice(-2);
remainingSeconds = ('0' + remainingSeconds).slice(-2);
return `${minutes}:${remainingSeconds}`
},
sliderChange(e) {
this.videoPrecent = e.detail.value
let designatedTime = (this.videoPrecent / 100) * this.sliderallTime
this.videoContext.seek(parseInt(designatedTime))
},
sliderChanging(e) {
this.showChanging = true
this.timerclear = true
this.precenting = e.detail.value
let changetiming = (this.precenting / 100) * this.sliderallTime
this.sliderchanging = this.formatSecondsToMMSS(Math.floor(changetiming));
},
onVideoPlay(index) {
// console.log("onVideoPlay")
}
},
onHide() {
this.videoContext.pause()
this.playFlag = false
},
onShow() {
if (this.videoContext) {
this.videoContext.play()
this.playFlag = true
}
}
}
</script>
<style lang="scss" scoped>
.swiper {
width: 750rpx;
}
.swiper-item {
width: 750rpx;
position: relative;
// background-color: red;
.fmBox {
width: 750rpx;
height: 500rpx;
position: absolute;
bottom: 0;
left: 0;
}
.txtWrap {
width: 750rpx;
height: 100px;
position: absolute;
bottom: 0;
left: 0;
padding: 10rpx 30rpx 0;
background: linear-gradient(to top, rgba(25, 25, 25, 1.0), rgba(118, 118, 118, 0.01));
justify-content: flex-end;
padding-bottom: 70rpx;
.nickname {
margin-bottom: 10rpx;
}
.tit {}
}
}
.iconWrap {
width: 750rpx;
height: 300rpx;
position: fixed;
top: 0;
left: 0;
.playIcon {
position: absolute;
left: 335rpx;
top: 400rpx;
width: 80rpx;
height: 80rpx;
}
.control_box {
width: 750rpx;
height: 40rpx;
position: absolute;
left: 0;
bottom: 0rpx;
flex-direction: row;
// background:linear-gradient(to top,rgba(0,0,0,1),rgba(94, 94, 94, 0.3)) ;
.sliderbox {
// transform: scale(0.9,0.9);
transform: scale(0.95);
}
.time {
width: 100rpx;
border: 1px solid blue;
}
}
.changing {
flex-direction: row;
position: absolute;
width: 270rpx;
height: 50rpx;
bottom: 220rpx;
left: 240rpx;
justify-content: center;
background-color: rgba(118, 118, 118, 0.1);
}
}
</style>
由于用v-if控制视频切换时播放暂停,所以在滑动时会有白屏,用户体验不好