shop-live/pages/live/spectator.nvue

360 lines
13 KiB
Plaintext
Raw Permalink Normal View History

2023-10-28 16:31:53 +08:00
<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.由于方法比较多,可以采取下面的方式查看代码:
1Mac按住 option 键,然后点击方法名,即可跳转到方法
2windows按住 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"
2023-10-31 20:41:54 +08:00
:style="boxStyle" :object-fit="object_fit" @timeupdate="timeupdate($event,i)"
@click="videoclick"
>
2023-10-28 16:31:53 +08:00
</video>
<!-- {{item}} {{i}} -->
</view>
2023-10-31 20:41:54 +08:00
<sd-float-page :room='room' :msgList='msgList' ref="childRef" :heightG='boxStyle.height'
2023-10-28 16:31:53 +08:00
:style="'width: '+ windowWidth +'px; height: '+ boxStyle.height +'px;position: absolute;' "></sd-float-page>
</view>
2023-10-31 20:41:54 +08:00
2023-10-28 16:31:53 +08:00
</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; //改变视频高度
2023-10-31 20:41:54 +08:00
console.log(this.boxStyle.height,'1111111111111111')
2023-10-28 16:31:53 +08:00
this.room = JSON.parse(decodeURIComponent(options.data));
2023-10-31 20:41:54 +08:00
2023-10-28 16:31:53 +08:00
this.get()
},
mounted() {
},
Ready() {},
methods: {
2023-10-31 20:41:54 +08:00
2023-10-28 16:31:53 +08:00
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>