<template>
<div class="video" ref="video">
<video ref="myvideo"
@canplay="getTotalTime"
@timeupdate="timeUpdate"
@ended="onended">
<source :src="url" />
</video>
<div class="controls">
<div class="progress">
<span @click="togglePlay"
:class="{'icon-play':isPaused,'icon-pause':!isPaused,'cursor':true}"></span>
<span>{{currentTime}}</span>
<div ref="progress"
class="progress_bar_box cursor"
@mousedown="getNowWh($event)"
@mouseup="mouseup($event)">
<div ref="onProgress"
:class="[
radiusLeft
? 'on_progress_bar_child border_Radius'
: 'on_progress_bar_child',
]">
<span v-show="!radiusLeft"
ref="mouseDom"
class="mouse_down"
@mousedown.stop="mousedown($event)"
@mouseup.stop="mouseup($event)"></span>
</div>
</div>
<span>{{duration}}</span>
</div>
<div class='bottom-bar'>
<div class="con_center">
<div class="button-rate">
<div class="rate-div-list">
<div class="rate-div-item"
v-for="item in rate"
:key="item.id"
@click="bindButtonRate"
:data-rate='item'>{{item}} x</div>
</div>
<div class="rate-div">
{{currentRate}} x
</div>
</div>
<div class="button-rate">
<div class="rate-div-list">
<div class="rate-div-item"
v-for="item in fastRate"
:key="item.id"
@click="bindButtonRateFast"
:data-rate='item'>{{item}} s</div>
</div>
<div class="rate-div">
快进
</div>
</div>
</div>
<div class="con_right">
<span @click="toggleMuted"
:class="{'icon-volume':!isMuted,'icon-volume-mute':isMuted,'cursor':true}"></span>
<span @click="toggleFullScreen"
:class="{'icon-enlarge':!isFullScreen ,'icon-shrink':isFullScreen,'cursor':true}"></span>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "VideoUser",
props: {
url: {
type: String,
default: "",
},
},
components: {
},
data() {
return {
myvideo: null,
video: null,
isPaused: true,
currentTime: "00:00",
duration: "00:00",
isMuted: false,
isFullScreen: false,
rate: [1, 1.5, 2, 3],
currentRate: 1,
fastRate: [3, 5, 10],
timer: null,
radiusLeft: false,
};
}, computed: {
}
,
mounted() {
this.myvideo = this.$refs.myvideo
this.video = this.$refs.video
},
watch: {
url(val){
this.url = val
this.myvideo.load();
}
},
methods: {
onended() {
this.isPaused = true;
this.currentTime = "00:00"
},
togglePlay() {
this.isPaused = !this.isPaused;
this.isPlay()
},
isPlay() {
if (this.isPaused) {
this.myvideo.pause()
clearInterval(this.timer);
this.timer = null;
} else {
this.myvideo.play()
this.timer = setInterval(this.setProgress, 60);
}
},
bindButtonRate(e) {
let rate = e.currentTarget.dataset.rate
this.currentRate = (Number(rate))
this.myvideo.playbackRate = this.currentRate
this.isPlay()
},
bindButtonRateFast(e) {
let rate = e.currentTarget.dataset.rate
let currentTime = (Number(rate)) + this.myvideo.currentTime
this.myvideo.currentTime = currentTime
this.setProgress()
this.isPlay()
},
timeFormat(time) {
let minute = Math.floor((time % 3600) / 60);
let second = Math.floor(time % 60);
minute = minute < 10 ? "0" + minute : minute;
second = second < 10 ? "0" + second : second;
return `${minute}:${second}`;
},
getTotalTime() {
this.currentTime = this.timeFormat(this.myvideo.currentTime);
this.duration = this.timeFormat(this.myvideo.duration);
},
timeUpdate() {
this.currentTime = this.timeFormat(this.myvideo.currentTime)
},
toggleMuted() {
this.isMuted = !this.isMuted
this.myvideo.muted = !this.myvideo.muted
},
toggleFullScreen(event) {
let fullscreen = document.webkitIsFullScreen || document.fullscreen;
this.isFullScreen = fullscreen
if (!this.isFullScreen) {
this.isFullScreen = !this.isFullScreen
const inFun = this.video.requestFullscreen || this.video.webkitRequestFullScreen;
inFun.call(this.video);
} else {
this.isFullScreen = !this.isFullScreen
const exitFun = document.exitFullscreen || this.document.webkitExitFullScreen;
exitFun.call(document);
}
},
setProgress() {
let progress = this.$refs.progress;
let onProgress = this.$refs.onProgress;
let mouseDom = this.$refs.mouseDom;
this.currentTime = this.timeFomat(this.myvideo.currentTime);
this.duration = this.timeFomat(this.myvideo.duration);
if (!this.myvideo.ended) {
this.radiusLeft = false;
let percent = this.myvideo.currentTime / this.myvideo.duration;
mouseDom &&
(mouseDom.style.left = percent * progress.offsetWidth + "px");
onProgress &&
(onProgress.style.width = percent * progress.offsetWidth + "px");
} else {
onProgress && (onProgress.style.width = "100%");
this.radiusLeft = true;
clearInterval(this.timer);
this.timer = null;
}
},
getNowWh(event) {
let ev = event || window.event;
this.videoSeek(ev.offsetX);
},
videoSeek(startx) {
if (this.isPaused || this.myvideo.ended) {
this.enhanceVideoSeek(startx);
} else {
this.myvideo.play();
this.enhanceVideoSeek(startx);
}
},
enhanceVideoSeek(moveWidth) {
clearInterval(this.timer);
let progress = this.$refs.progress;
let onProgress = this.$refs.onProgress;
let percent = moveWidth / progress.offsetWidth;
onProgress &&
(onProgress.style.width = percent * progress.offsetWidth + "px");
this.myvideo.currentTime = percent * this.myvideo.duration;
this.timer = setInterval(this.setProgress, 60);
},
mousedown(event) {
let that = this;
let ev = event || window.event;
let _target = ev.target;
let startx = ev.clientX;
let sb_bkx = startx - ev.target.offsetLeft;
let allwh = this.$refs.progress.clientWidth;
let ww = document.documentElement.clientWidth;
let wh = window.innerHeight;
if (ev.preventDefault) {
ev.preventDefault();
} else {
ev.returnValue = false;
}
document.onmousemove = function (ev) {
let evt = ev || window.event;
if (
evt.clientY < 0 ||
evt.clientX < 0 ||
evt.clientY > wh ||
evt.clientX > ww
) {
return false;
}
let endx = evt.clientX - sb_bkx;
if (endx > -1 && endx < allwh) {
_target.style.left = endx + "px";
that.enhanceVideoSeek(endx);
} else {
document.onmousemove = null;
}
};
},
mouseup(e) {
document.onmousemove = null;
},
timeFomat(time) {
let h = Math.floor(time / 3600);
let m = Math.floor((time % 3600) / 60);
let s = Math.floor(time % 60);
m = m >= 10 ? m : "0" + m;
s = s >= 10 ? s : "0" + s;
if (h === 0) {
return m + ":" + s;
}
return h + ":" + m + ":" + s;
},
}
}
</script>
<style lang='scss' scoped>
.video {
position: relative;
}
.video video {
width: 100%;
height: 100%;
}
.controls {
width: 100%;
height: 50px;
position: absolute;
bottom: 0;
left: 0;
background-color: #22222261;
display: flex;
padding: 5px;
flex-direction: column;
}
.controls span {
padding: 0 5px;
color: #fff;
}
.button-rate {
width: 40px;
text-align: center;
height: 20px;
position: relative;
cursor: pointer;
margin: 0 5px;
left: -11px;
}
.rate-div {
width: 100%;
color: #fff;
position: absolute;
left: 0;
top: 0;
}
.rate-div-list {
color: #595959;
text-align: center;
visibility: hidden;
position: absolute;
width: 100%;
bottom: 20px;
background: #fff;
z-index: 99999999;
width: 150px;
box-shadow: 2px 2px 2px #888888;
}
.rate-div-item:hover {
background: #ebebeb;
}
.rate-div-item{
padding: 10px 5px;
}
.button-rate:hover .rate-div-list {
visibility: initial;
}
.con_center {
display: flex;
}
.bottom-bar{
display: flex;
justify-content: space-between;
align-items: center;
}
.progress{
margin-bottom: 5px;
display: flex;
justify-content: space-between;padding: 5px 0 0 0;align-items: center;
}
.audio_progress {
width: 100%;
position: relative;
height: 2px;
display: flex;
align-items: center;
cursor:pointer;
user-select: none;
outline: none;background:#c1c2c3
}
.audio_progress_line {
position: absolute;
height: 2px;
width: 100%;
background-color: #000;
left: 0;
top: 50%;
margin-top: -1px;
}
.audio_progress_dot {
position: absolute;
top: 50%;
width: 12px;
height: 12px;
background-color: #000000;
color: #c1c2c3;
border-radius: 50%;
transform: translate(-50%, -50%);
cursor: pointer;
}
.progress_bar_box {
flex: 1;
margin:0 16px 0 16px;
height: 8px;
background: rgba(205, 206, 209, 0.2);
border-radius: 5px;
box-sizing: border-box;
position: relative;
.on_progress_bar_child {
width: 0;
height: 100%;
background: #fff;
border-radius:4px;
// overflow: hidden;
position: absolute;
top: 0;
left: 0;
z-index: 1001;
// .mouse_down {
// position: absolute;
// width: 5px;
// height:10px;
// left: 100%;
// background: #fff;
// border-radius: 50%;
// z-index: 1002;
// cursor: pointer;
// }
}
.on_progress_bar_child.border_Radius {
border-radius: 4px;
}
}
.cursor{
cursor: pointer;
}
</style>