Add files
This commit is contained in:
parent
e9a3fa5fc2
commit
a3c15adc94
5 changed files with 479 additions and 0 deletions
215
src/functions/buttons.js
Normal file
215
src/functions/buttons.js
Normal file
|
@ -0,0 +1,215 @@
|
|||
const video = document.querySelector('.plyx-player')
|
||||
const videoContainer = document.querySelector('.video-container')
|
||||
|
||||
function AddControls() {
|
||||
var add_controls = `
|
||||
<div class="plyx-player-controls">
|
||||
<div class="row-1">
|
||||
<div class="row-1-start">
|
||||
<button id="play-pause"><i class="fa-solid fa-play"></i></button>
|
||||
<button id="skip-back"><i class="fa-solid fa-arrow-rotate-left"></i></button>
|
||||
<button id="skip-forth"><i class="fa-solid fa-arrow-rotate-right"></i></button>
|
||||
<input class="volume" id="volume" value="1" type="range" max="1" min="0" step="0.01">
|
||||
<div class="volume-controls">
|
||||
<button data-title="Mute (m)" class="volume-button" id="volume-button"><i class="fa-solid fa-volume-high"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-1-end">
|
||||
<div class="time">
|
||||
<time id="time-elapsed">00:00</time>
|
||||
<span> / </span>
|
||||
<time id="duration">00:00</time>
|
||||
</div>
|
||||
<button id="fullscreen"><i class="fa-solid fa-expand"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-2">
|
||||
<div class="video-progress">
|
||||
<progress id="progress-bar" value="0" min="0"></progress>
|
||||
<input class="seek" id="seek" value="0" min="0" type="range" step="1">
|
||||
<div class="seek-tooltip" id="seek-tooltip">00:00</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
video.insertAdjacentHTML("afterend", add_controls);
|
||||
}
|
||||
|
||||
function Util() {
|
||||
const videoControls = document.querySelector('.plyx-player-controls')
|
||||
// Play/Plause
|
||||
const Button_PlayPause = document.querySelector('.plyx-player-controls #play-pause')
|
||||
|
||||
Button_PlayPause.addEventListener('click', Toggle_PlayPause)
|
||||
video.addEventListener('click', Toggle_PlayPause)
|
||||
video.addEventListener('play', Update_PlayPauseButton)
|
||||
video.addEventListener('pause', Update_PlayPauseButton)
|
||||
|
||||
function Toggle_PlayPause() {
|
||||
if (video.paused || video.ended) {
|
||||
video.play()
|
||||
}
|
||||
else {
|
||||
video.pause()
|
||||
}
|
||||
}
|
||||
|
||||
function Update_PlayPauseButton() {
|
||||
if (video.paused) {
|
||||
Button_PlayPause.setAttribute('data-title', 'Play (k)')
|
||||
Button_PlayPause.innerHTML = `<i class="fa-solid fa-play"></i>`
|
||||
} else {
|
||||
Button_PlayPause.setAttribute('data-title', 'Pause (k)')
|
||||
Button_PlayPause.innerHTML = `<i class="fa-solid fa-pause"></i>`
|
||||
}
|
||||
}
|
||||
|
||||
// Fullscreen
|
||||
const Button_Fullscreen = document.getElementById('fullscreen');
|
||||
function Toggle_Fullscreen() {
|
||||
if (document.fullscreenElement) {document.exitFullscreen()}
|
||||
else if (document.webkitFullscreenElement) {document.webkitExitFullscreen()}
|
||||
else if (videoContainer.webkitRequestFullscreen) {videoContainer.webkitRequestFullscreen()}
|
||||
else {videoContainer.requestFullscreen()}
|
||||
}
|
||||
|
||||
Button_Fullscreen.onclick = Toggle_Fullscreen;
|
||||
function Update_FullscreenButton() {
|
||||
if (document.fullscreenElement) {
|
||||
Button_Fullscreen.setAttribute('data-title', 'Exit full screen (f)')
|
||||
Button_Fullscreen.innerHTML = `<i class="fa-solid fa-compress"></i>`
|
||||
} else {
|
||||
Button_Fullscreen.setAttribute('data-title', 'Full screen (f)')
|
||||
Button_Fullscreen.innerHTML = `<i class="fa-solid fa-expand"></i>`
|
||||
}
|
||||
}
|
||||
|
||||
videoContainer.addEventListener('fullscreenchange', Update_FullscreenButton);
|
||||
|
||||
// Skip Back or Forth
|
||||
const Button_SkipBack = document.querySelector('.plyx-player-controls #skip-back')
|
||||
const Button_SkipForth = document.querySelector('.plyx-player-controls #skip-forth')
|
||||
|
||||
Button_SkipBack.addEventListener('click', Toggle_SkipBack)
|
||||
Button_SkipForth.addEventListener('click', Toggle_SkipForth)
|
||||
|
||||
function Toggle_SkipBack() {Skip(-10)}
|
||||
function Toggle_SkipForth() {Skip(10)}
|
||||
|
||||
function Skip(value) {
|
||||
video.currentTime += value;
|
||||
}
|
||||
|
||||
// Volume (Also the slider)
|
||||
const Button_Volume = document.getElementById('volume-button')
|
||||
const volume = document.getElementById('volume')
|
||||
function Update_Volme() {
|
||||
if (video.muted) {
|
||||
video.muted = false
|
||||
}
|
||||
video.volume = volume.value
|
||||
}
|
||||
|
||||
volume.addEventListener('input', Update_Volme)
|
||||
|
||||
function Update_Volume_Icon() {
|
||||
Button_Volume.setAttribute('data-title', 'Mute (m)')
|
||||
|
||||
if (video.muted || video.volume === 0) {
|
||||
Button_Volume.innerHTML = `<i class="fa-solid fa-volume-slash"></i>`
|
||||
Button_Volume.setAttribute('data-title', 'Unmute (m)')
|
||||
} else if (video.volume > 0 && video.volume <= 0.5) {
|
||||
Button_Volume.innerHTML = `<i class="fa-solid fa-volume-low"></i>`
|
||||
} else {
|
||||
Button_Volume.innerHTML = `<i class="fa-solid fa-volume-high"></i>`
|
||||
}
|
||||
}
|
||||
|
||||
video.addEventListener('volumechange', Update_Volume_Icon)
|
||||
|
||||
function Toggle_Mute() {
|
||||
video.muted = !video.muted;
|
||||
|
||||
if (video.muted) {
|
||||
volume.setAttribute('data-volume', volume.value)
|
||||
volume.value = 0;
|
||||
} else {
|
||||
volume.value = volume.dataset.volume
|
||||
}
|
||||
}
|
||||
Button_Volume.addEventListener('click', Toggle_Mute)
|
||||
|
||||
// Keyboard Shortcuts
|
||||
function keyboardShortcuts(event) {
|
||||
const { key } = event;
|
||||
switch(key) {
|
||||
case 'k':
|
||||
Toggle_PlayPause();
|
||||
if (video.paused) {
|
||||
Show_Controls();
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
Hide_Controls();
|
||||
}, 2000);
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
Toggle_Mute();
|
||||
break;
|
||||
case 'f':
|
||||
Toggle_Fullscreen();
|
||||
break;
|
||||
case 'j':
|
||||
Toggle_SkipBack();
|
||||
break;
|
||||
case 'l':
|
||||
Toggle_SkipForth();
|
||||
break;
|
||||
}
|
||||
}
|
||||
document.addEventListener('keyup', keyboardShortcuts);
|
||||
|
||||
// Auto Hide Controls
|
||||
function Hide_Controls() {
|
||||
if (video.paused) {
|
||||
return
|
||||
}
|
||||
|
||||
videoControls.classList.add('hide')
|
||||
console.log('0')
|
||||
}
|
||||
|
||||
// Show_Controls displays the video controls
|
||||
function Show_Controls() {
|
||||
videoControls.classList.remove('hide')
|
||||
console.log('1')
|
||||
}
|
||||
video.addEventListener('mouseenter', Show_Controls)
|
||||
video.addEventListener('mouseleave', Hide_Controls)
|
||||
videoControls.addEventListener('mouseenter', Show_Controls)
|
||||
videoControls.addEventListener('mouseleave', Hide_Controls)
|
||||
|
||||
var mouseTimer = null, cursorVisible = true
|
||||
|
||||
function disappearCursor() {
|
||||
mouseTimer = null
|
||||
document.body.style.cursor = "none"
|
||||
cursorVisible = false
|
||||
Hide_Controls()
|
||||
}
|
||||
|
||||
document.onmousemove = function() {
|
||||
if (mouseTimer) {
|
||||
window.clearTimeout(mouseTimer);
|
||||
Show_Controls();
|
||||
}
|
||||
if (!cursorVisible) {
|
||||
document.body.style.cursor = "default"
|
||||
cursorVisible = true
|
||||
}
|
||||
mouseTimer = window.setTimeout(disappearCursor, 1500)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export {AddControls, Util}
|
75
src/functions/length.js
Normal file
75
src/functions/length.js
Normal file
|
@ -0,0 +1,75 @@
|
|||
const video = document.querySelector('.plyx-player')
|
||||
|
||||
function VideoLength() {
|
||||
// Duration and Length of Video
|
||||
const timeElapsed = document.getElementById('time-elapsed');
|
||||
const duration = document.getElementById('duration');
|
||||
|
||||
function formatTime(timeInSeconds) {
|
||||
const result = new Date(timeInSeconds * 1000).toISOString().substr(11, 8);
|
||||
|
||||
return {
|
||||
minutes: result.substr(3, 2),
|
||||
seconds: result.substr(6, 2),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
function initializeVideo() {
|
||||
const videoDuration = Math.round(video.duration);
|
||||
const time = formatTime(videoDuration);
|
||||
duration.innerText = `${time.minutes}:${time.seconds}`;
|
||||
duration.setAttribute('datetime', `${time.minutes}m ${time.seconds}s`);
|
||||
}
|
||||
video.addEventListener('loadedmetadata', initializeVideo);
|
||||
function updateTimeElapsed() {
|
||||
const time = formatTime(Math.round(video.currentTime));
|
||||
timeElapsed.innerText = `${time.minutes}:${time.seconds}`;
|
||||
timeElapsed.setAttribute('datetime', `${time.minutes}m ${time.seconds}s`);
|
||||
}
|
||||
video.addEventListener('timeupdate', updateTimeElapsed);
|
||||
|
||||
// Progress Bar
|
||||
const progressBar = document.getElementById('progress-bar');
|
||||
const seek = document.getElementById('seek');
|
||||
function initializeVideo() {
|
||||
const videoDuration = Math.round(video.duration);
|
||||
seek.setAttribute('max', videoDuration);
|
||||
progressBar.setAttribute('max', videoDuration);
|
||||
const time = formatTime(videoDuration);
|
||||
duration.innerText = `${time.minutes}:${time.seconds}`;
|
||||
duration.setAttribute('datetime', `${time.minutes}m ${time.seconds}s`)
|
||||
}
|
||||
|
||||
function updateProgress() {
|
||||
seek.value = Math.floor(video.currentTime);
|
||||
progressBar.value = Math.floor(video.currentTime);
|
||||
}
|
||||
|
||||
video.addEventListener('timeupdate', updateProgress);
|
||||
|
||||
const seekTooltip = document.getElementById('seek-tooltip');
|
||||
|
||||
function updateSeekTooltip(event) {
|
||||
const skipTo = Math.round((event.offsetX / event.target.clientWidth) * parseInt(event.target.getAttribute('max'), 10));
|
||||
seek.setAttribute('data-seek', skipTo)
|
||||
const t = formatTime(skipTo);
|
||||
seekTooltip.textContent = `${t.minutes}:${t.seconds}`;
|
||||
const rect = video.getBoundingClientRect();
|
||||
seekTooltip.style.left = `${event.pageX - rect.left}px`;
|
||||
}
|
||||
|
||||
seek.addEventListener('mousemove', updateSeekTooltip);
|
||||
|
||||
function skipAhead(event) {
|
||||
const skipTo = event.target.dataset.seek ? event.target.dataset.seek : event.target.value;
|
||||
video.currentTime = skipTo;
|
||||
progressBar.value = skipTo;
|
||||
seek.value = skipTo;
|
||||
}
|
||||
seek.addEventListener('input', skipAhead);
|
||||
|
||||
initializeVideo()
|
||||
}
|
||||
|
||||
export {VideoLength}
|
0
src/functions/progress-bar.js
Normal file
0
src/functions/progress-bar.js
Normal file
8
src/index.js
Normal file
8
src/index.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
import {Util, AddControls} from './functions/buttons.js'
|
||||
import {VideoLength} from './functions/length.js'
|
||||
|
||||
AddControls()
|
||||
setTimeout(() => {
|
||||
Util()
|
||||
VideoLength()
|
||||
}, 0o100);
|
181
src/styles/app.css
Normal file
181
src/styles/app.css
Normal file
|
@ -0,0 +1,181 @@
|
|||
.plyx-player {
|
||||
width: 100%;
|
||||
display: inline-flex;
|
||||
}
|
||||
.video-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.plyx-player-controls {
|
||||
display: inline-flex;
|
||||
right: 0;
|
||||
left: 0;
|
||||
padding: 10px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
transition: all 0.2s ease;
|
||||
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.5));
|
||||
flex-direction: inherit;
|
||||
}
|
||||
.row-1 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
.row-1-start {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.row-1-end {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
button {
|
||||
aspect-ratio: 1;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
margin: 0px 6px;
|
||||
}
|
||||
button:hover {
|
||||
background: rgba(44, 44, 44, 0.6);
|
||||
border-radius: 6px;
|
||||
}
|
||||
#volume-button svg {
|
||||
aspect-ratio: 1;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
fill: white;
|
||||
padding: 3px 0px 0px 0px;
|
||||
}
|
||||
.video-controls.hide {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.video-progress {
|
||||
position: relative;
|
||||
height: 6.4px;
|
||||
margin: 6px -10px -8px -10px;
|
||||
}
|
||||
progress {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border-radius: 2px;
|
||||
width: 100%;
|
||||
height: 8.4px;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
progress::-webkit-progress-bar {
|
||||
background-color: #474545;
|
||||
border-radius: 2px;
|
||||
}
|
||||
progress::-webkit-progress-value {
|
||||
background: red;
|
||||
border-radius: 2px;
|
||||
}
|
||||
progress::-moz-progress-bar {
|
||||
border: none;
|
||||
background: #ff7e7e;
|
||||
}
|
||||
.seek {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
}
|
||||
.seek:hover + .seek-tooltip {
|
||||
display: block;
|
||||
}
|
||||
.seek-tooltip {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: -50px;
|
||||
margin-left: -20px;
|
||||
font-size: 12px;
|
||||
padding: 3px;
|
||||
content: attr(data-title);
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
input[type=range] {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
height: 8.4px;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type=range]:focus {
|
||||
outline: none;
|
||||
}
|
||||
input[type=range]:focus::-webkit-slider-runnable-track {
|
||||
background: transparent;
|
||||
}
|
||||
input[type=range]:focus::-moz-range-track {
|
||||
outline: none;
|
||||
}
|
||||
input[type=range]::-webkit-slider-runnable-track {
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
border-radius: 1.3px;
|
||||
-webkit-appearance: none;
|
||||
transition: all 0.4s ease;
|
||||
}
|
||||
input[type=range]::-webkit-slider-thumb {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
border-radius: 16px;
|
||||
background: red;
|
||||
cursor: pointer;
|
||||
-webkit-appearance: none;
|
||||
margin-left: -1px;
|
||||
}
|
||||
input[type=range]::-moz-range-track {
|
||||
width: 100%;
|
||||
height: 8.4px;
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
background: transparent;
|
||||
border-radius: 0;
|
||||
}
|
||||
input[type=range].volume {
|
||||
height: 5px;
|
||||
background-color: #fff;
|
||||
}
|
||||
input[type=range].volume::-webkit-slider-runnable-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
input[type=range].volume::-webkit-slider-thumb {
|
||||
margin-left: 0;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
background: #fff;
|
||||
}
|
||||
input[type=range].volume::-moz-range-thumb {
|
||||
border: 1px solid #fff;
|
||||
background: #fff;
|
||||
}
|
||||
input[type="range"]::-moz-range-thumb {
|
||||
height: 12px;
|
||||
width: 6px;
|
||||
border-radius: 0px;
|
||||
border: none;
|
||||
background: #f00;
|
||||
cursor: pointer;
|
||||
}
|
||||
.hide {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
#progress-bar {
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
Reference in a new issue