216 lines
4.8 KiB
Plaintext
216 lines
4.8 KiB
Plaintext
<template>
|
|
<view
|
|
@touchstart.stop="touchstart"
|
|
@touchmove.stop="touchmove"
|
|
@touchend.stop="touchend">
|
|
<slot></slot>
|
|
</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;
|
|
let plusTime = parseInt(Math.abs(precent * duration));
|
|
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:
|
|
this.$emit('onGestureEvent', {
|
|
type: this.downLeft ? 'LEFT_DOWN' : 'RIGHT_DOWN',
|
|
position
|
|
});
|
|
break;
|
|
// 上滑
|
|
case -2:
|
|
this.$emit('onGestureEvent', {
|
|
type: this.downLeft ? 'LEFT_UP' : 'RIGHT_UP',
|
|
position
|
|
});
|
|
break;
|
|
// 左滑
|
|
case 0:
|
|
this.swipeDir = type;
|
|
countTime(position);
|
|
this.$emit('onGestureEvent', {
|
|
type: 'SEEK_TIME_UPDATE',
|
|
finalTime
|
|
});
|
|
break;
|
|
// 右滑
|
|
case 1:
|
|
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;
|
|
}
|
|
this.$emit('onGestureEvent', {
|
|
type: 'TOUCH_END'
|
|
});
|
|
break;
|
|
// doubleTap
|
|
case 4:
|
|
break;
|
|
// tap
|
|
case 5:
|
|
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 isXchange = () => {
|
|
if (Math.abs(X) > Math.abs(Y)) {
|
|
position = X;
|
|
hasType = 'X';
|
|
isJustTouch = false;
|
|
}
|
|
if (X >= 0) excuteCb(1);
|
|
// 左滑
|
|
else excuteCb(0);
|
|
};
|
|
|
|
const isYchange = () => {
|
|
if (Math.abs(Y) > Math.abs(X)) {
|
|
position = Y;
|
|
hasType = 'Y';
|
|
isJustTouch = false;
|
|
}
|
|
if (Y >= 0) excuteCb(-1);
|
|
// 上滑
|
|
else excuteCb(-2);
|
|
};
|
|
|
|
const countDirect = () => {
|
|
if (hasType) {
|
|
hasType === 'X' ? isXchange() : isYchange();
|
|
return;
|
|
}
|
|
if (Math.abs(X) > 5) {
|
|
isXchange();
|
|
return;
|
|
}
|
|
if (Math.abs(Y) > 5) {
|
|
isYchange();
|
|
}
|
|
};
|
|
|
|
this.handleTouch = (type, e) => {
|
|
switch(type) {
|
|
case 'start':
|
|
startX = e.touches[0].screenX;
|
|
startY = e.touches[0].screenY;
|
|
T = Date.now();
|
|
hasType = '';
|
|
isJustTouch = true;
|
|
this.downLeft = startX < this.halfWidth ? true : false;
|
|
break;
|
|
case 'move':
|
|
moveEndX = e.touches[0].screenX;
|
|
moveEndY = e.touches[0].screenY;
|
|
X = moveEndX - startX;
|
|
Y = moveEndY - startY;
|
|
// console.log('Y', Y);
|
|
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);
|
|
},
|
|
limit(num, min, max) {
|
|
if (num < min) return min;
|
|
if (num > max) return max;
|
|
return num;
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style></style>
|
|
|