358 lines
13 KiB
Plaintext
358 lines
13 KiB
Plaintext
|
<template>
|
|||
|
<view class="container">
|
|||
|
<view :style="'width: '+ windowWidth +'px; height: '+ boxStyle.height +'px;z-inde:-1;'">
|
|||
|
<!--
|
|||
|
1.这里的 swiper 不是用来控制视频滑动的,而是用来控制左右滑动的,如果不需要的可以改成 view
|
|||
|
2.为了 视频无限加载,已经把 21 行的 appear 去掉了,加上了 loadmore 方法(第10行)
|
|||
|
3.由于方法比较多,可以采取下面的方式查看代码:
|
|||
|
(1)Mac:按住 option 键,然后点击方法名,即可跳转到方法
|
|||
|
(2)windows:按住 Alt 键,然后鼠标左击,即可跳转到方法
|
|||
|
-->
|
|||
|
<list @loadmore="getData" @scroll="scrolls" :loadmoreoffset="wHeight*1" :show-scrollbar="false"
|
|||
|
ref="listBox" :pagingEnabled="true" :scrollable="true">
|
|||
|
<!-- 循环数据 -->
|
|||
|
<cell v-for="(item,i) in dataList" :key="i">
|
|||
|
<!-- 用div把视频模组套起来 -->
|
|||
|
<div :style="'width: '+ windowWidth +'px; height: '+ boxStyle.height +'px;'">
|
|||
|
<!-- <view v-if="Math.abs(k-i)<=1"> -->
|
|||
|
<view v-if="Math.abs(k-i)<=1">
|
|||
|
<view class="root">
|
|||
|
<video :ref="'item'+i" :id="item.id" :loop="true" :autoplay="i == k"
|
|||
|
:src="item.pull_url" :muted="item.isplay" :enable-progress-gesture="false"
|
|||
|
:page-gesture="false" :controls="false" :show-loading="true" :is-live='true'
|
|||
|
@error='vedioerr' :show-fullscreen-btn="false" :show-center-play-btn="false"
|
|||
|
:style="boxStyle" :object-fit="object_fit" @timeupdate="timeupdate($event,i)">
|
|||
|
|
|||
|
</video>
|
|||
|
<!-- {{item}} {{i}} -->
|
|||
|
|
|||
|
</view>
|
|||
|
<sd-float-page :room='room' :msgList='msgList'
|
|||
|
:style="'width: '+ windowWidth +'px; height: '+ boxStyle.height +'px;position: absolute;' "></sd-float-page>
|
|||
|
</view>
|
|||
|
|
|||
|
</div>
|
|||
|
</cell>
|
|||
|
</list>
|
|||
|
</view>
|
|||
|
|
|||
|
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
<script>
|
|||
|
import list from '@/uni_modules/uview-ui/libs/config/props/list';
|
|||
|
import sdFloatPage from '@/components/sd-live-page/livepage.nvue';
|
|||
|
import {
|
|||
|
VUE_APP_WS_URL
|
|||
|
} from '@/config/app';
|
|||
|
|
|||
|
import json from '../../static/js/json';
|
|||
|
export default {
|
|||
|
components: {
|
|||
|
sdFloatPage
|
|||
|
},
|
|||
|
data() {
|
|||
|
return {
|
|||
|
imgHost: '',
|
|||
|
//下面打🌟号的是必须要的基础字段
|
|||
|
//下面打💗号的是拥有滑动条的必须字段
|
|||
|
dataList: [], //用于数据循环的列表🌟💗
|
|||
|
wHeight: 0, //获取的屏幕高度🌟💗
|
|||
|
boxStyle: { //视频,图片封面样式🌟💗
|
|||
|
'height': 0,
|
|||
|
'width': 0,
|
|||
|
},
|
|||
|
k: 0, //默认为0🌟💗
|
|||
|
max: 2,
|
|||
|
playIngIds: [], //正在播放的视频id列队,列队用于处理滑动过快导致的跳频问题🌟💗
|
|||
|
ready: false, //可忽略
|
|||
|
isDragging: false, //false代表停止滑动🌟💗
|
|||
|
refreshing: true, //用于下拉刷新🌟💗
|
|||
|
windowWidth: 0, //获取屏幕宽度🌟💗
|
|||
|
windowHeight: 0,
|
|||
|
dex: [0, 0], //用于判断是上滑还是下滑,第一个存旧值,第二个存新值【目前在1.0.7已经废弃】
|
|||
|
currents: 0, //用于左右滑动,0代表视频界面,1代表右滑界面🌟💗
|
|||
|
platform: '', //用于获取操作系统:ios、android🌟💗
|
|||
|
playIng: false, //用于视频初始化时是否播放,默认不播放🌟💗
|
|||
|
videoTime: '', //视频总时长,这个主要用来截取时间数值💗
|
|||
|
videoTimes: '', //视频时长,用这个来获取时间值,例如:00:30这个时间值💗
|
|||
|
changeTime: '', //显示滑动进度条时变化的时间💗
|
|||
|
isShowimage: false, //是否显示封面【1.0.4已废弃,但是意思需要记住】
|
|||
|
currenttimes: 0, //当前时间💗
|
|||
|
isShowProgressBarTime: false, //是否拖动进度条,如果拖动(true)则显示进度条时间,否则不显示(false)【1.0.4已废弃,但是意思需要记住】
|
|||
|
ProgressBarOpacity: 0.7, //进度条不拖动时的默认值,就是透明的💗
|
|||
|
dotWidth: 0, //播放的小圆点,默认没有💗
|
|||
|
deleteHeight: 0, //测试高度🌟💗
|
|||
|
percent: 0, //百分小数💗
|
|||
|
currentPosition: 0, //滑块当前位置💗//2.0已弃用,现已用于后端参数
|
|||
|
currentPositions: 0, //滑块当前位置的副本💗//2.0已弃用,现已用于后端参数
|
|||
|
newTime: 0, //跟手滑动后的最新时间💗
|
|||
|
timeNumber: 0, //🌟💗
|
|||
|
ProgressBarBottom: 20, //进度条离底部的距离💗
|
|||
|
object_fit: 'cover', //视频样式默认包含🌟💗
|
|||
|
mode: 'aspectFit', //图片封面样式🌟💗
|
|||
|
timeout: "", //🌟用来阻止 setTimeout()方法
|
|||
|
voice: "", //🌟用来阻止 setTimeout()方法
|
|||
|
oldVideo: "",
|
|||
|
isAutoplay: false, //是否开启自动播放(默认不开启)
|
|||
|
autoplayText: "开启自动播放",
|
|||
|
msgList: [],
|
|||
|
room: {},
|
|||
|
socketTask: null,
|
|||
|
userName: '',
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
watch: {
|
|||
|
async k(new_k, old_k) { //监听 k 值的变化,可以控制视频的播放与暂停
|
|||
|
const max = new_k + 2;
|
|||
|
if (this.max < max) {
|
|||
|
this.max = max;
|
|||
|
}
|
|||
|
// if (this.oldCurrent != this.currentNav) {
|
|||
|
// this.oldCurrent = this.currentNav
|
|||
|
// return false
|
|||
|
// }
|
|||
|
this.dataList[old_k].playIng = false //如果视频暂停,就加载封面
|
|||
|
this.dataList[old_k].isplay = true
|
|||
|
this.dataList[old_k].state = 'pause'
|
|||
|
// console.log('预留第' + (old_k) + '个视频:' + this.dataList[old_k].community_id)
|
|||
|
// 2.0版本已经去掉了下面这一句,视频不用暂停,只需要把声音禁止就行
|
|||
|
uni.createVideoContext(this.dataList[old_k].community_id, this)
|
|||
|
.pause() //如果视频暂停,那么旧视频停止,这里的this.dataList[old_k].id + '' + old_k,后面加 old_k 是为了每一个视频的 id 值不同,这样就可以大程度的避免串音问题
|
|||
|
// console.log('已经暂停 --> 第' + (old_k) + '个视频~') //提示
|
|||
|
this.dataList[new_k].state = 'play'
|
|||
|
this.dataList[new_k].isplay = false
|
|||
|
this.dataList[new_k].playIng = true
|
|||
|
uni.createVideoContext(this.dataList[new_k].community_id, this).play()
|
|||
|
}
|
|||
|
},
|
|||
|
onShow() {
|
|||
|
uni.hideLoading();
|
|||
|
// console.log('回到前台' + this.dataList.length);
|
|||
|
if (this.dataList.length !== 0) {
|
|||
|
this.dataList[this.k].state = 'play';
|
|||
|
setTimeout(() => {
|
|||
|
uni.createVideoContext(this.dataList[this.k].id, this).play()
|
|||
|
}, 250)
|
|||
|
}
|
|||
|
},
|
|||
|
onHide() {
|
|||
|
this.dataList[this.k].state = 'pause'; //界面隐藏也要停止播放视频
|
|||
|
setTimeout(() => {
|
|||
|
uni.createVideoContext(this.dataList[this.k].community_id, this).pause(); //暂停以后继续播放
|
|||
|
}, 250)
|
|||
|
// console.log('到后台');
|
|||
|
},
|
|||
|
onLoad(options) {
|
|||
|
this.platform = uni.getSystemInfoSync().platform
|
|||
|
this.windowWidth = uni.getSystemInfoSync().screenWidth //获取屏幕宽度
|
|||
|
this.boxStyle.width = this.windowWidth + 'px' //给宽度加px
|
|||
|
this.wHeight = uni.getSystemInfoSync().screenHeight; //获取屏幕高度
|
|||
|
this.boxStyle.height = this.wHeight; //改变视频高度
|
|||
|
console.log(this.boxStyle.height)
|
|||
|
this.room = JSON.parse(decodeURIComponent(options.data));
|
|||
|
|
|||
|
this.get()
|
|||
|
|
|||
|
},
|
|||
|
mounted() {
|
|||
|
|
|||
|
},
|
|||
|
Ready() {},
|
|||
|
methods: {
|
|||
|
|
|||
|
|
|||
|
|
|||
|
autoPlay() {
|
|||
|
this.isAutoplay = !this.isAutoplay;
|
|||
|
if (!this.isAutoplay) {
|
|||
|
this.autoplayText = "开启自动播放"
|
|||
|
uni.showToast({
|
|||
|
title: "关闭自动播放",
|
|||
|
icon: 'none',
|
|||
|
duration: 3000
|
|||
|
})
|
|||
|
} else {
|
|||
|
this.autoplayText = "关闭自动播放"
|
|||
|
uni.showToast({
|
|||
|
title: "开启自动播放",
|
|||
|
icon: 'none',
|
|||
|
duration: 3000
|
|||
|
})
|
|||
|
}
|
|||
|
},
|
|||
|
getData() {
|
|||
|
// 这里就是数据加载完以后再向后端发送数据的地方,
|
|||
|
|
|||
|
|
|||
|
},
|
|||
|
vedioerr(e) {
|
|||
|
let timer = null
|
|||
|
if (e.tye = 'error') {
|
|||
|
timer = setInterval((res) => {
|
|||
|
uni.createVideoContext('myVideo', this).play()
|
|||
|
console.log('重新连接', '1111111111')
|
|||
|
}, 600000)
|
|||
|
} else {
|
|||
|
timer = null
|
|||
|
}
|
|||
|
|
|||
|
},
|
|||
|
|
|||
|
touchstart(event) {
|
|||
|
this.dataList[this.k].isShowimage = true //刚触摸的时候就要显示预览视频图片了
|
|||
|
this.dataList[this.k].isShowProgressBarTime = true //显示时间线
|
|||
|
this.ProgressBarOpacity = 1 //让滑块显示起来更明显一点
|
|||
|
this.dotWidth = 10 //让点显示起来更明显一点
|
|||
|
},
|
|||
|
touchend() { //当手松开后,跳到最新时间
|
|||
|
uni.createVideoContext(this.dataList[this.k].community_id, this).seek(this.newTime)
|
|||
|
if (this.dataList[this.k].state == 'pause') {
|
|||
|
this.dataList[this.k].state = 'play'
|
|||
|
uni.createVideoContext(this.dataList[this.k].community_id, this).play()
|
|||
|
}
|
|||
|
this.dataList[this.k].isShowProgressBarTime = false //触摸结束后,隐藏时间线
|
|||
|
this.dataList[this.k].isShowimage = false //触摸结束后,隐藏时间预览
|
|||
|
this.ProgressBarOpacity = 0.5 //隐藏起来进度条,不那么明显了
|
|||
|
this.dotWidth = 0 //隐藏起来进度条,不那么明显了
|
|||
|
},
|
|||
|
touchmove(event) { //当手移动滑块时,计算位置、百分小数、新的时间
|
|||
|
var msg = []
|
|||
|
if (this.videoTime !== '') {
|
|||
|
msg = this.videoTime.split(':')
|
|||
|
}
|
|||
|
var timeNumber = Number(msg[0]) * 60 + Number(msg[1])
|
|||
|
this.currentPositions = event.changedTouches[0].screenX
|
|||
|
this.percent = this.currentPositions / this.windowWidth
|
|||
|
this.newTime = this.percent * timeNumber
|
|||
|
this.currenttimes = parseInt(this.newTime)
|
|||
|
let theTime = this.newTime
|
|||
|
let middle = 0; // 分
|
|||
|
if (theTime > 60) {
|
|||
|
middle = parseInt(theTime / 60);
|
|||
|
theTime = parseInt(theTime % 60);
|
|||
|
}
|
|||
|
this.changeTime =
|
|||
|
`${Math.round(middle)>9?Math.round(middle):'0'+Math.round(middle)}:${Math.round(theTime)>9?Math.round(theTime):'0'+Math.round(theTime)}`
|
|||
|
},
|
|||
|
timeupdate(event, index) { //计算滑块当前位置,计算当前百分小数
|
|||
|
if (index == this.k) {
|
|||
|
var currenttime = event.detail.currentTime
|
|||
|
this.timeNumber = Math.round(event.detail.duration)
|
|||
|
this.getTime()
|
|||
|
this.percent = currenttime / this.timeNumber
|
|||
|
this.currentPosition = this.windowWidth * this.percent
|
|||
|
let theTime = currenttime
|
|||
|
let middle = 0; // 分
|
|||
|
if (theTime > 60) {
|
|||
|
middle = parseInt(theTime / 60);
|
|||
|
theTime = parseInt(theTime % 60);
|
|||
|
}
|
|||
|
this.changeTime =
|
|||
|
`${Math.round(middle)>9?Math.round(middle):'0'+Math.round(middle)}:${Math.round(theTime)>9?Math.round(theTime):'0'+Math.round(theTime)}`
|
|||
|
//自动切换视频
|
|||
|
if (this.isAutoplay) { //true,代表自动播放
|
|||
|
if (Math.round(currenttime) == this.timeNumber - 1) {
|
|||
|
const dom = uni.requireNativePlugin('dom')
|
|||
|
let doms = 'item' + (this.k + 1)
|
|||
|
setTimeout(() => {
|
|||
|
let el = this.$refs[doms][0]
|
|||
|
dom.scrollToElement(el, {
|
|||
|
offset: 0,
|
|||
|
animated: true
|
|||
|
})
|
|||
|
}, 500)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
getTime() { //得到时间函数
|
|||
|
this.videoTime = this.formatSeconds(this.timeNumber);
|
|||
|
var msg = []
|
|||
|
if (this.videoTime !== '') {
|
|||
|
msg = this.videoTime.split(':')
|
|||
|
}
|
|||
|
this.videoTimes = `${msg[0]>9?msg[0]:'0'+msg[0]}:${msg[1]>9?msg[1]:'0'+msg[1]}`;
|
|||
|
},
|
|||
|
formatSeconds(value) { //获取时间函数
|
|||
|
let theTime = parseInt(value); // 秒
|
|||
|
let middle = 0; // 分
|
|||
|
if (theTime > 60) {
|
|||
|
middle = parseInt(theTime / 60);
|
|||
|
theTime = parseInt(theTime % 60);
|
|||
|
}
|
|||
|
return `${middle>9?middle:middle}:${theTime>9?theTime:theTime}`;
|
|||
|
},
|
|||
|
moreVideo(index) {
|
|||
|
|
|||
|
},
|
|||
|
toVideo(index) {
|
|||
|
|
|||
|
},
|
|||
|
scrolls(event) {
|
|||
|
|
|||
|
this.showManage = false;
|
|||
|
this.isDragging = event.isDragging;
|
|||
|
if (!event.isDragging) { //isDragging:判断用户是不是在滑动,滑动:true,停止滑动:false。我们要用户停止滑动时才给 k 赋值,这样就可以避免很多麻烦
|
|||
|
var i = Math.round(Math.abs(event.contentOffset.y) / (this.wHeight - this.deleteHeight +
|
|||
|
1)) //先用绝对值取出滑动的距离,然后除以屏幕高度,取一个整,就知道你现在滑动到哪一个视频了
|
|||
|
if (i !== this.k) { //这里加判断是因为这个方法会执行很多次,会造成重复请求,所以这里写一个限制
|
|||
|
if (uni.getSystemInfoSync().platform == 'ios') {
|
|||
|
this.k = i //判断了用户没有滑动,确认了用户的确是在看这个视频,然后就赋值啦
|
|||
|
this.dataList[this.k].state = 'play'
|
|||
|
// console.log('正在播放 --> 第' + (this.k + 1) + '个视频~')
|
|||
|
} else {
|
|||
|
clearTimeout(this.timers);
|
|||
|
this.timers = setTimeout(() => {
|
|||
|
this.k = i //判断了用户没有滑动,确认了用户的确是在看这个视频,然后就赋值啦
|
|||
|
this.dataList[this.k].state = 'play'
|
|||
|
// console.log('正在播放 --> 第' + (this.k + 1) + '个视频~')
|
|||
|
}, 80)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
get() {
|
|||
|
let that = this
|
|||
|
var msg = [this.room];
|
|||
|
console.log(this.room)
|
|||
|
for (let i = 0; i < msg.length; i++) {
|
|||
|
msg[i]['isMore'] = false
|
|||
|
msg[i]['playIng'] = false
|
|||
|
msg[i]['state'] = false
|
|||
|
msg[i]['isplay'] = false
|
|||
|
msg[i]['loading'] = false
|
|||
|
msg[i]['id'] = msg[i]['live_stream_id']
|
|||
|
}
|
|||
|
this.dataList = msg;
|
|||
|
|
|||
|
if (this.dataList.length !== 0) {
|
|||
|
|
|||
|
this.dataList[this.k].state = 'play';
|
|||
|
uni.createVideoContext(this.dataList[this.k].id, this).play()
|
|||
|
this.page = that.page + 1
|
|||
|
}
|
|||
|
|
|||
|
console.log(this.dataList, this.dataList[this.k].id, 222222)
|
|||
|
},
|
|||
|
onpullingdown() {
|
|||
|
this.refreshing = true
|
|||
|
},
|
|||
|
onrefresh() {
|
|||
|
setTimeout(() => {
|
|||
|
this.refreshing = false
|
|||
|
}, 1000)
|
|||
|
},
|
|||
|
|
|||
|
},
|
|||
|
onReachBottom() {
|
|||
|
uni.$emit('onReachBottom');
|
|||
|
},
|
|||
|
}
|
|||
|
</script>
|
|||
|
<style lang="scss" scoped>
|
|||
|
|
|||
|
</style>
|