You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
xshop/resources/js/client-vue/videoPlayer.vue

239 lines
5.7 KiB
Vue

<template>
<div class="mp4-player">
<video ref="p" :src="link" class="video" :poster="cover"></video>
<div class="seek-container">
<div ref="seekbar" class="seekbar" @click="seek">
<div class="progress-seek" :style="progressPercent"></div>
</div>
</div>
<div class="player-buttons">
<div>
{{ currentTime }}
</div>
<button type="button" class="rw p-btn" @click="timeOffset(-10)">
<i class="ri-rewind-line"></i>
</button>
<button type="button" class="sp p-btn" @click="speedChange">
<i class="ri-speed-up-line"></i>
</button>
<button type="button" class="play-pause" @click="playPause">
<i class="ri-play-line" v-if="!isPlay"></i>
<i class="ri-pause-line" v-if="isPlay"></i>
</button>
<button type="button" class="stop p-btn" @click="stopNow" >
<i class="ri-stop-line"></i>
</button>
<button type="button" class="sp p-btn" @click="timeOffset(10)">
<i class="ri-speed-line"></i>
</button>
<button type="button" class="sp p-btn" @click="fullScreen">
<i class="ri-fullscreen-line"></i>
</button>
<div>
{{ fullTime }}
</div>
</div>
</div>
</template>
<script>
export default {
name: "video-player",
components: {},
data: () => {
return {
link: '',
currentTime: '00:00',
fullTime: '00:00',
isPlay: false,
full: 0,
current: 0,
speed: 2,
speeds: [
.5,
.75,
1.0,
1.25,
1.5,
1.75,
2.0,
]
}
},
props: {
asset: {
required: true
},
cover:{
default: null,
}
},
mounted() {
window.addEventListener('load',()=>{
setTimeout(() => {
this.link = this.asset;
document.querySelector('#video-preview-botz').style.display = 'none';
}, 500);
setInterval(() => {
this.updatePlayer();
}, 300);
});
},
computed: {
progressPercent() {
if (this.full != 0) {
return 'width:' + (this.current * 100) / this.full + '%;';
}
return 'width: 0%;';
}
},
methods: {
fullScreen(){
this.$refs.p.requestFullscreen();
},
speedChange() {
this.speed++;
if (this.speed === this.speeds.length){
this.speed = 0;
}
this.$refs.p.playbackRate = this.speeds[this.speed];
window.$toast.success('Speed: '+this.speeds[this.speed])
},
seek(e) {
const req = e.offsetX * 100 / this.$refs.seekbar.clientWidth;
this.$refs.p.currentTime = req * this.full / 100;
},
timeOffset(sec) {
this.$refs.p.currentTime += sec;
},
stopNow() {
let p = this.$refs.p;
p.pause();
p.currentTime = 0;
},
playPause() {
let p = this.$refs.p;
if (this.isPlay) {
p.pause();
} else {
p.play();
}
},
updatePlayer() {
try {
let p = this.$refs.p;
if (!isNaN(p.duration)) {
this.fullTime = this.toHHMMSS(p.duration);
this.currentTime = this.toHHMMSS(p.currentTime);
this.full = p.duration;
this.current = p.currentTime;
}
this.isPlay = ! p.paused;
} catch {
}
},
toHHMMSS(secs) {
let sec_num = parseInt(secs, 10)
let hours = Math.floor(sec_num / 3600)
let minutes = Math.floor(sec_num / 60) % 60
let seconds = sec_num % 60
return [hours, minutes, seconds]
.map(v => v < 10 ? "0" + v : v)
.filter((v, i) => v !== "00" || i > 0)
.join(":")
}
}
}
</script>
<style scoped>
.mp4-player {
border: 1px solid var(--xshop-primary);
padding: 1rem;
border-radius: var(--xshop-border-radius);
overflow: hidden;
}
.seekbar {
height: 4px;
margin-bottom: 16px;
background: silver;
overflow: hidden;
transition: 300ms;
border-radius: var(--xshop-border-radius);
}
.seek-container {
padding: .75rem 0;
height: 50px;
&:hover {
.seekbar {
height: 20px;
margin-bottom: 0;
}
}
}
.progress-seek {
height: 20px;
width: 10%;
background: silver;
transition: 295ms;
transition-timing-function: linear;
background: var(--xshop-primary);
}
.player-buttons {
display: flex;
align-items: center;
justify-content: space-evenly;
}
.play-pause {
background: var(--xshop-primary);
color: var(--xshop-diff);
font-size: 45px;
width: 75px;
height: 75px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
border-width: 0;
i.ri-play-line {
width: 40px;
}
}
.p-btn {
border-width: 0;
background: var(--xshop-secondary);
color: var(--xshop-diff2);
font-size: 30px;
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
}
.video{
width: 100%;
border-radius: var(--xshop-border-radius);
}
</style>