shop-live/pages/live/spectator.nvue

358 lines
13 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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"
: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>