保利视频

This commit is contained in:
zoujiandong
2026-02-04 10:12:59 +08:00
parent a7b2a673a9
commit db9ca707ae
11 changed files with 2089 additions and 19 deletions
@@ -0,0 +1,97 @@
/**
* @file 拖动进度提示组件
*/
<template>
<view class="plv-player-drag-tips">
<view class="plv-player-drag-tips__box">
<image class="plv-player-drag-tips__direction-img" :src="imgSrc"
@error="imageError">
</image>
<text class="plv-player-drag-tips__time">
{{changeTimeFormat}} / {{durationFormat}}
</text>
</view>
</view>
</template>
<script>
import utils from '@/common/util.js';
import backImg from '@/static/skin/back.png';
import forwardImg from '@/static/skin/forward.png'
export default {
props: {
currentTime: {
type: Number
},
duration: {
type: Number
},
changeTime: {
type: Number
}
},
data() {
return {
isForward: false
}
},
watch: {
changeTime(newValue, oldValue){
this.isForward = newValue > oldValue;
}
},
computed: {
timeFormatType() {
this.duration >= 3600 ? 2 : 1;
},
changeTimeFormat() {
return utils.formatTimeByDuration(this.changeTime, this.timeFormatType);
},
durationFormat() {
return utils.formatTimeByDuration(this.duration, this.timeFormatType)
},
imgSrc() {
return this.isForward ? forwardImg : backImg;
}
}
}
</script>
<style>
.plv-player-drag-tips {
width: 250rpx;
height: 160rpx;
background: rgba(0,0,0,.7);
border-radius: 10rpx;
}
.plv-player-drag-tips__box {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
justify-content: center;
align-items: center;
}
.plv-player-drag-tips__direction-img {
width: 100rpx;
height: 100rpx;
}
.plv-player-drag-tips__time {
font-size: 24rpx;
color: #FFFFFF;
}
</style>
+271
View File
@@ -0,0 +1,271 @@
<template>
<view class="plv-player-gesture"
@touchstart="touchstart"
@touchmove="touchmove"
@longpress="handleLongPress"
@touchcancel="handleTouchCancel"
@touchend="touchend">
</view>
</template>
<script>
export default {
props: {
// 屏幕宽度(物理像素)
holeWidth: Number,
// 视频总时长
duration: Number,
// 视频当前播放时间
currentTime: Number
},
computed: {
halfWidth() {
return parseInt(this.holeWidth / 2);
}
},
data() {
return {
// 是否在左区域按下手势
downLeft: false,
// 滑动方向
swipeDir: null
}
},
mounted() {
this.addHandler();
},
methods:{
addHandler() {
// 增加父容器左右滑动监听
let finalTime = -1;
// 计算左右滑动seek进度
const countTime = (position) => {
const { holeWidth, duration, currentTime } = this;
const precent = Math.abs(position) / holeWidth;
const nowTime = currentTime || 0;
const constSecond = duration < 60 ? duration : 60;
let plusTime = parseInt(Math.abs(precent * constSecond));
if (position < 0) plusTime = plusTime * -1;
finalTime = nowTime + plusTime;
finalTime = this.limit(finalTime, 0, duration);
return finalTime;
};
this.addGesture((type, position) => {
switch (type) {
// 下滑
case -1:
// console.log('//下滑');
this.$emit('onGestureEvent', {
type: this.downLeft ? 'LEFT_DOWN' : 'RIGHT_DOWN',
position
});
break;
// 上滑
case -2:
// console.log('//上滑');
this.$emit('onGestureEvent', {
type: this.downLeft ? 'LEFT_UP' : 'RIGHT_UP',
position
});
break;
// 左滑
case 0:
// console.log('//左滑');
this.swipeDir = type;
countTime(position);
this.$emit('onGestureEvent', {
type: 'SEEK_TIME_UPDATE',
finalTime
});
break;
// 右滑
case 1:
// console.log('//右滑');
this.swipeDir = type;
countTime(position);
this.$emit('onGestureEvent', {
type: 'SEEK_TIME_UPDATE',
finalTime
});
break;
// touchend for swipe
case 3:
if (this.swipeDir > -1) {
this.$emit('onGestureEvent', {
type: this.swipeDir ? 'SWIPE_RIGHT' : 'SWIPE_LEFT'
});
this.swipeDir = -1;
}
if (finalTime > -1) {
this.$emit('onGestureSeekTo', finalTime);
finalTime = -1;
}
break;
// doubleTap
case 4:
// console.log('>>>> 双击');
this.$emit('onGestureEvent', {
type: 'DOUBLE_CLICK'
});
break;
// tap
case 5:
// console.log('>>>> 单击');
this.handleClick();
break;
// longTap
case 6:
break;
}
});
},
addGesture(callback) {
const { options } = this;
let startX, startY, moveEndX, moveEndY, X, Y, position, hasType;
let T, lastTap, isJustTouch = true;
const excuteCb = (type) => {
// type 手势类型 -2 上滑 -1 下滑 0 左滑 1 右滑 2 just touch 3 touchend 4 doubleTap 5 tap 6 longTap
if (callback && typeof callback === 'function')
callback(type, position);
};
const YPlus = 20;
const YReduce = YPlus * -1;
const XPlus = 50;
const XReduce = XPlus * -1;
const isXchange = () => {
if (X > XPlus || X < XReduce) {
position = X;
hasType = 'X';
isJustTouch = false;
}
if (X > XPlus) excuteCb(1);
// 左滑
else if (X < XReduce) excuteCb(0);
};
const isYchange = () => {
if (Y > YPlus || Y < YReduce) {
position = Y;
hasType = 'Y';
isJustTouch = false;
}
if (Y > YPlus) excuteCb(-1);
// 上滑
else if (Y < YReduce) excuteCb(-2);
};
const countDirect = () => {
if (hasType) {
hasType === 'X' ? isXchange() : isYchange();
return;
}
isXchange();
isYchange();
};
this.handleTouch = (type, e) => {
switch(type) {
case 'start':
startX = e.changedTouches[0].pageX;
startY = e.changedTouches[0].pageY;
T = Date.now();
hasType = '';
isJustTouch = true;
this.downLeft = startX < this.halfWidth ? true : false;
break;
case 'move':
moveEndX = e.changedTouches[0].pageX;
moveEndY = e.changedTouches[0].pageY;
X = moveEndX - startX;
Y = moveEndY - startY;
countDirect();
break;
case 'end':
if (isJustTouch)
if (lastTap && Date.now() - lastTap <= 300)
excuteCb(4);
else if (Date.now() - T < 1000)
excuteCb(5);
else
excuteCb(6);
else
excuteCb(3);
lastTap = Date.now();
isJustTouch = true;
break;
}
};
},
handleClick() {
this.$emit('onGestureClick');
},
touchstart(e) {
this.handleTouch('start', e);
},
touchmove(e) {
this.handleTouch('move', e);
},
touchend(e) {
this.handleTouch('end', e);
this.$emit('onTouchEnd');
},
handleTouchCancel() {
this.$emit('onTouchCancel');
},
handleLongPress() {
this.$emit('onLongPress');
},
/**
* 控制最小值,最大值
* @param num
* @param min
* @param max
* @returns {*}
*/
limit(num, min, max) {
if (num < min) return min;
if (num > max) return max;
return num;
}
}
}
</script>
<style>
.plv-player-gesture {
flex: 1;
flex-direction: row;
}
.plv-player-gesture__left {
flex: 5;
}
.plv-player-gesture__right {
flex: 5;
}
</style>
+68
View File
@@ -0,0 +1,68 @@
<template>
<view v-if="isShow" class="plv-player-icon">
<image class="plv-player-icon__img" :src="imgUrl"></image>
<text class="plv-player-icon__text">{{ precent + '%' }}</text>
</view>
</template>
<script>
export default {
props: {
imgUrl: {
type: 'string',
required: true
},
precent: {
type: 'Number',
default: 100,
required: true
}
},
watch: {
precent(num) {
if (!this.isShow) this.isShow = true;
this.startClock();
}
},
data() {
return {
isShow: false
}
},
methods: {
startClock() {
this.clearClock();
this.clock = setTimeout(() => {
this.isShow = false;
}, 1500);
},
clearClock() {
if (this.clock) clearTimeout(this.clock);
this.clock = null;
}
}
}
</script>
<style>
.plv-player-icon {
align-items: center;
justify-content: center;
}
.plv-player-icon__img {
width: 80rpx;
height: 80rpx;
}
.plv-player-icon__text {
color: #FFFFFF;
text-align: center;
}
</style>
File diff suppressed because it is too large Load Diff
+92
View File
@@ -0,0 +1,92 @@
<template>
<view v-if="isShow" class="plv-player-volume-wrap">
<image class="plv-player-volume__img" :src="value === 0 ? muteImgUrl : imgUrl "></image>
<view class="plv-player-volume__progress">
<view class="plv-player-volume__progress__played" :style="'flex:' + value"></view>
<view class="plv-player-volume__progress_surplus" :style="'flex:' + valueLeft"></view>
</view>
</view>
</template>
<script>
export default {
props: {
imgUrl: {
type: 'string',
required: true
},
muteImgUrl: {
type: 'string',
required: true
},
value: {
type: 'Number',
default: 0.5,
required: true
}
},
watch: {
value(num) {
if (!this.isShow) this.isShow = true;
this.startClock();
}
},
computed: {
valueLeft() {
return 1 - this.value;
}
},
data() {
return {
isShow: false
}
},
methods: {
startClock() {
this.clearClock();
this.clock = setTimeout(() => {
this.isShow = false;
}, 1500);
},
clearClock() {
if (this.clock) clearTimeout(this.clock);
this.clock = null;
}
}
}
</script>
<style>
.plv-player-volume-wrap {
flex-direction: row;
align-items: center;
justify-content: center;
}
.plv-player-volume__img {
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
.plv-player-volume__progress {
width: 260rpx;
height: 8rpx;
flex-direction: row;
background-color: #09BB07;
}
.plv-player-volume__progress__played {
background-color: #007AFF;
}
.plv-player-volume__progress_surplus {
background-color: #FFFFFF;
}
</style>