A Pen by André Givenchy on CodePen.
Last active
November 19, 2022 10:30
-
-
Save andregivenchy/03260ca48baf2ecaca4a317ea8d0f78f to your computer and use it in GitHub Desktop.
Segern-Custom-HTML5-VideoPlayer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<body> | |
<div class="video-container"> | |
<video id="video" disableRemotePlayback poster="https://cdn-std.droplr.net/files/acc_205555/d00I61" src="https://cdn.viqeo.tv/storage/72/59/eb441789490697bc2e574bd8a83e5d04.mp4"></video> | |
<div class="player-state"> | |
<span class="state-btn state-backward"> | |
<ion-icon name="play-back-outline"></ion-icon> | |
<span class="backward-duration">5</span> | |
</span> | |
<span class="main-state state-btn"> | |
<ion-icon name="play-outline"></ion-icon> | |
</span> | |
<span class="custom-loader"></span> | |
<span class="state-btn state-forward"> | |
<span class="forward-duration">5</span> | |
<ion-icon name="play-forward-outline"></ion-icon> | |
</span> | |
</div> | |
<div class="controls"> | |
<div class="duration"> | |
<div class="current-time"></div> | |
<div class="hover-time"> | |
<span class="hover-duration"></span> | |
</div> | |
<div class="buffer"></div> | |
</div> | |
<div class="btn-controls"> | |
<div class="btn-con"> | |
<span class="play-pause control-btn"> | |
<ion-icon name="play-outline"></ion-icon> | |
</span> | |
<span class="volume"> | |
<span class="mute-unmute control-btn"> | |
<ion-icon name="volume-high-outline"></ion-icon> | |
</span> | |
<div class="max-vol"> | |
<div class="current-vol"></div> | |
</div> | |
</span> | |
<span class="time-container"> | |
<span class="current-duration">0:00</span> | |
<span>/</span> | |
<span class="total-duration">0:00</span> | |
</span> | |
</div> | |
<div class="right-controls"> | |
<span class="backward control-btn" title="5 backward"> | |
<ion-icon name="play-back-outline"></ion-icon> | |
</span> | |
<span class="forward control-btn" title="5 forward"> | |
<ion-icon name="play-forward-outline"></ion-icon> | |
</span> | |
<span class="mini-player control-btn"> | |
<ion-icon name="albums-outline"></ion-icon> | |
</span> | |
<span class="settings control-btn"> | |
<span class="setting-btn"> | |
<ion-icon name="options-outline"></ion-icon> | |
</span> | |
<ul class="setting-menu"> | |
<li data-value="0.25">0.25x</li> | |
<li data-value="0.5">0.5x</li> | |
<li data-value="0.75">0.75x</li> | |
<li data-value="1" class="speed-active">1x</li> | |
<li data-value="1.25">1.25x</li> | |
<li data-value="1.5">1.5x</li> | |
<li data-value="1.75">1.75x</li> | |
<li data-value="2">2x</li> | |
</ul> | |
</span> | |
<span class="theater-btn control-btn"> | |
<span class="theater-default"> | |
<ion-icon name="tablet-landscape-outline"></ion-icon> | |
</span> | |
<span class="theater-active"> | |
<ion-icon name="tv-outline"></ion-icon> | |
</span> | |
</span> | |
<span class="fullscreen-btn control-btn" title="fullscreen"> | |
<span class="full"> | |
<ion-icon name="scan-outline"></ion-icon> | |
</span> | |
<span class="contract"> | |
<ion-icon name="contract-outline"></ion-icon> | |
</span> | |
</span> | |
</div> | |
</div> | |
</div> | |
</div> | |
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.video-container { | |
width: 1024px; | |
height: calc((9 / 16) * 1024px); | |
position: relative; | |
color: #ffffff; | |
overflow: hidden; | |
background: rgb(255, 255, 255, 1.0); | |
border-radius: .5rem; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
} | |
.video-container video { | |
max-width: 100%; | |
max-height: 100%; | |
} | |
.custom-loader { | |
position: absolute; | |
width: 50px; | |
height: 50px; | |
border-radius: 50%; | |
border-top: 5px solid transparent; | |
border-right: 5px solid #ffffff; | |
border-left: 5px solid #ffffff; | |
border-bottom: 5px solid #ffffff; | |
z-index: 9999; | |
animation: rotation 2s infinite linear; | |
-webkit-animation: rotation 2s infinite linear; | |
display: none; | |
} | |
.player-state { | |
display: flex; | |
position: absolute; | |
width: 100%; | |
justify-content: space-around; | |
} | |
.state-btn { | |
font-size: 2.3rem; | |
width: 80px; | |
height: 80px; | |
cursor: pointer; | |
border-radius: 50%; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275); | |
background: rgba(1, 2, 3, 0.25); | |
backdrop-filter: blur(10px); | |
z-index: 9999; | |
-webkit-tap-highlight-color: transparent; | |
opacity: 0; | |
user-select: none; | |
transform: scale(0); | |
} | |
.state-forward, | |
.state-backward { | |
font-size: 1.5rem; | |
} | |
.state-forward .forward-duration { | |
margin-right: 0.5rem; | |
} | |
.state-backward .backward-duration { | |
margin-left: 0.5rem; | |
} | |
.animate-state { | |
animation: playPause 0.5s forwards; | |
} | |
.show-state { | |
transform: scale(1); | |
opacity: 1; | |
} | |
.show-controls { | |
opacity: 1 !important; | |
transform: translateY(0) !important; | |
visibility: visible !important; | |
} | |
.controls { | |
position: absolute; | |
bottom: 0; | |
left: 0; | |
padding: 0rem 1rem 0.5rem 1rem; | |
width: 100%; | |
background: linear-gradient(to top, #000000b8 -100%, transparent); | |
backdrop-filter: blur(0px); | |
box-sizing: border-box; | |
opacity: 0; | |
transform: translateY(40px); | |
visibility: hidden; | |
z-index: 99; | |
transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94); | |
user-select: none; | |
-webkit-tap-highlight-color: transparent; | |
} | |
.duration { | |
position: relative; | |
width: 100%; | |
height: .5rem; | |
background: rgb(255, 255, 255, 0.0); | |
backdrop-filter: blur(10px); | |
cursor: pointer; | |
transition: all 0.2s; | |
} | |
.duration:hover { | |
height: .5rem; | |
} | |
.duration .buffer { | |
height: 100%; | |
position: absolute; | |
inset: 0; | |
background-color: rgb(255, 255, 255, .05); | |
backdrop-filter: blur(10px); | |
z-index: 9; | |
width: 0; | |
} | |
.hover-time { | |
height: 100%; | |
position: absolute; | |
inset: 0; | |
background: #ffffff9a; | |
z-index: 99; | |
display: flex; | |
align-items: center; | |
width: 0; | |
} | |
.hover-time .hover-duration { | |
position: absolute; | |
right: calc((-25px / 2)); | |
top: -25px; | |
background: #3c3c3ca7; | |
padding: 0.2rem; | |
border-radius: 5px; | |
font-size: 0.7rem; | |
visibility: hidden; | |
font-weight: bold; | |
opacity: 0; | |
transform: scale(0); | |
} | |
.duration:hover .hover-time .hover-duration { | |
visibility: visible; | |
opacity: 1; | |
transition: all 0.2s; | |
transform: scale(1); | |
} | |
.duration .current-time { | |
height: 100%; | |
position: absolute; | |
inset: 0; | |
background: rgb(0, 0, 0, 1.0); | |
z-index: 999; | |
display: flex; | |
align-items: center; | |
width: 0; | |
} | |
.current-time::before { | |
content: ""; | |
position: absolute; | |
right: calc((-15px / 2)); | |
background: #ff1900; | |
width: .5rem; | |
height: 1.5rem; | |
border-radius: 5%; | |
transition: all 0.2s; | |
visibility: hidden; | |
transform: scale(0); | |
} | |
.duration:hover .current-time::before { | |
visibility: visible; | |
transform: scale(1); | |
} | |
.btn-controls { | |
padding-top: 1rem; | |
font-size: 1.2rem; | |
display: flex; | |
align-items: center; | |
justify-content: space-between; | |
} | |
.btn-con { | |
display: flex; | |
align-items: center; | |
} | |
.btn-con, | |
.btn-controls > span { | |
cursor: pointer; | |
} | |
.play-pause { | |
display: flex; | |
margin-right: 0.5rem; | |
} | |
.control-btn { | |
width: 2.2rem; | |
height: 2.2rem; | |
border-radius: 50%; | |
background: rgb(1, 2, 3, 0.0); | |
backdrop-filter: blur(0px); | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
border: 1px solid transparent; | |
box-sizing: border-box; | |
position: relative; | |
margin-right: 0.5rem; | |
} | |
.control-btn:last-child { | |
margin-right: 0; | |
} | |
.control-btn:hover { | |
background: rgb(1, 2, 3, 0.15); | |
backdrop-filter: blur(10px); | |
} | |
.control-btn::before { | |
content: ""; | |
display: block; | |
width: 100%; | |
height: 100%; | |
border-radius: 50%; | |
background: #2424246a; | |
position: absolute; | |
transition: all 0.1s; | |
transform: scale(0); | |
} | |
.control-btn:active::before { | |
transform: scale(1); | |
border: 1px solid #3131315c; | |
} | |
.time-container { | |
font-size: 13px; | |
font-weight: 500; | |
padding-left: 0.7rem; | |
} | |
.volume { | |
display: flex; | |
align-items: center; | |
cursor: default; | |
margin-right:1rem; | |
} | |
.mute-unmute { | |
display: flex; | |
cursor: pointer; | |
} | |
.max-vol { | |
height: 3px; | |
cursor: pointer; | |
background: #ffffff6e; | |
transition: all 0.1s; | |
width: 0; | |
visibility: hidden; | |
transform: scaleX(0); | |
transform-origin: left; | |
display: flex; | |
align-items: center; | |
} | |
.max-vol.show { | |
width: 56px; | |
visibility: visible; | |
transform: scaleX(1); | |
} | |
.current-vol { | |
position: absolute; | |
inset: 0; | |
width: 20%; | |
height: 100%; | |
background: #fff; | |
display: flex; | |
transition: none; | |
align-items: center; | |
} | |
.current-vol::before { | |
content: ""; | |
position: absolute; | |
right: -5px; | |
width: 12px; | |
height: 12px; | |
display: block; | |
border-radius: 50%; | |
background: #eee; | |
} | |
.setting-menu { | |
opacity: 0; | |
visibility: hidden; | |
list-style: none; | |
padding-inline-start: 0; | |
margin-block-start: 0; | |
margin-block-end: 0; | |
position: absolute; | |
bottom: 4.5rem; | |
transition: all 0.2s; | |
background: rgba(28, 28, 28, 0.9); | |
transform: scaleY(0); | |
transform-origin: bottom; | |
border-radius: 5px; | |
} | |
.setting-menu li { | |
padding: 0.3rem 2rem; | |
margin: 0.5rem; | |
transition: all 0.2s; | |
border-radius: 5px; | |
font-size: 0.9rem; | |
font-weight: 500; | |
} | |
.speed-active { | |
background: rgb(23, 23, 23); | |
} | |
.setting-menu li:hover { | |
background: rgb(31, 31, 31); | |
} | |
.setting-btn { | |
display: flex; | |
} | |
.show-setting-menu { | |
opacity: 1; | |
transform: scaleY(1); | |
visibility: visible; | |
} | |
.theater { | |
width: 100% !important; | |
} | |
.theater-btn .theater-default, | |
.theater-btn .theater-active { | |
display: flex; | |
} | |
.video-container.theater .theater-default { | |
display: none; | |
} | |
.video-container:not(.theater) .theater-active { | |
display: none; | |
} | |
.fullscreen { | |
position: absolute !important; | |
max-width: 100% !important; | |
width: 100% !important; | |
height: 100% !important; | |
display: flex !important; | |
background: #000 !important; | |
align-items: center !important; | |
} | |
.right-controls { | |
display: flex; | |
align-items: center; | |
} | |
.right-controls span { | |
cursor: pointer; | |
} | |
.full, | |
.contract { | |
display: none; | |
} | |
.video-container:not(.fullscreen) .full { | |
display: flex; | |
} | |
.video-container.fullscreen .contract { | |
display: flex; | |
} | |
@keyframes playPause { | |
50% { | |
opacity: 1; | |
transform: scale(1.1); | |
} | |
100% { | |
opacity: 0; | |
transform: scale(1); | |
} | |
} | |
@keyframes rotation { | |
from { | |
transform: rotate(0deg); | |
} | |
to { | |
transform: rotate(360deg); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const video = document.querySelector("video"); | |
const fullscreen = document.querySelector(".fullscreen-btn"); | |
const playPause = document.querySelector(".play-pause"); | |
const volume = document.querySelector(".volume"); | |
const currentTime = document.querySelector(".current-time"); | |
const duration = document.querySelector(".duration"); | |
const buffer = document.querySelector(".buffer"); | |
const totalDuration = document.querySelector(".total-duration"); | |
const currentDuration = document.querySelector(".current-duration"); | |
const controls = document.querySelector(".controls"); | |
const videoContainer = document.querySelector(".video-container"); | |
const currentVol = document.querySelector(".current-vol"); | |
const totalVol = document.querySelector(".max-vol"); | |
const mainState = document.querySelector(".main-state"); | |
const muteUnmute = document.querySelector(".mute-unmute"); | |
const forward = document.querySelector(".forward"); | |
const backward = document.querySelector(".backward"); | |
const hoverTime = document.querySelector(".hover-time"); | |
const hoverDuration = document.querySelector(".hover-duration"); | |
const miniPlayer = document.querySelector(".mini-player"); | |
const settingsBtn = document.querySelector(".setting-btn"); | |
const settingMenu = document.querySelector(".setting-menu"); | |
const theaterBtn = document.querySelector(".theater-btn"); | |
const speedButtons = document.querySelectorAll(".setting-menu li"); | |
const backwardSate = document.querySelector(".state-backward"); | |
const forwardSate = document.querySelector(".state-forward"); | |
const loading = document.querySelector(".custom-loader"); | |
let isPlaying = false, | |
mouseDownProgress = false, | |
mouseDownVol = false, | |
isCursorOnControls = false, | |
muted = false, | |
timeout, | |
volumeVal = 1, | |
mouseOverDuration = false, | |
touchClientX = 0, | |
touchPastDurationWidth = 0, | |
touchStartTime = 0; | |
currentVol.style.width = volumeVal * 100 + "%"; | |
// Video Event Listeners | |
video.addEventListener("loadedmetadata", canPlayInit); | |
video.addEventListener("play", play); | |
video.addEventListener("pause", pause); | |
video.addEventListener("progress", handleProgress); | |
videoContainer.addEventListener("click", toggleMainState); | |
video.onwaiting = function () { | |
loading.style.display = "block"; | |
}; | |
video.onplaying = function () { | |
loading.style.display = "none"; | |
}; | |
fullscreen.addEventListener("click", toggleFullscreen); | |
videoContainer.addEventListener("fullscreenchange", () => { | |
videoContainer.classList.toggle("fullscreen", document.fullscreenElement); | |
}); | |
playPause.addEventListener("click", (e) => { | |
if (!isPlaying) { | |
play(); | |
} else { | |
pause(); | |
} | |
}); | |
duration.addEventListener("click", navigate); | |
duration.addEventListener("mousedown", (e) => { | |
mouseDownProgress = true; | |
navigate(e); | |
}); | |
totalVol.addEventListener("mousedown", (e) => { | |
mouseDownVol = true; | |
handleVolume(e); | |
}); | |
document.addEventListener("mouseup", (e) => { | |
mouseDownProgress = false; | |
mouseDownVol = false; | |
}); | |
document.addEventListener("mousemove", handleMousemove); | |
duration.addEventListener("mouseenter", (e) => { | |
mouseOverDuration = true; | |
}); | |
duration.addEventListener("mouseleave", (e) => { | |
mouseOverDuration = false; | |
hoverTime.style.width = 0; | |
hoverDuration.innerHTML = ""; | |
}); | |
videoContainer.addEventListener("mouseleave", hideControls); | |
videoContainer.addEventListener("mousemove", (e) => { | |
controls.classList.add("show-controls"); | |
hideControls(); | |
}); | |
videoContainer.addEventListener("touchstart", (e) => { | |
controls.classList.add("show-controls"); | |
touchClientX = e.changedTouches[0].clientX; | |
const currentTimeRect = currentTime.getBoundingClientRect(); | |
touchPastDurationWidth = currentTimeRect.width; | |
touchStartTime = e.timeStamp; | |
}); | |
videoContainer.addEventListener("touchend", () => { | |
hideControls(); | |
touchClientX = 0; | |
touchPastDurationWidth = 0; | |
touchStartTime = 0; | |
}); | |
videoContainer.addEventListener("touchmove", touchNavigate); | |
function touchNavigate(e) { | |
hideControls(); | |
if (e.timeStamp - touchStartTime > 500) { | |
const durationRect = duration.getBoundingClientRect(); | |
const clientX = e.changedTouches[0].clientX; | |
const value = Math.min( | |
Math.max( | |
0, | |
touchPastDurationWidth + (clientX - touchClientX) * 0.2 | |
), | |
durationRect.width | |
); | |
currentTime.style.width = value + "px"; | |
video.currentTime = (value / durationRect.width) * video.duration; | |
currentDuration.innerHTML = showDuration(video.currentTime); | |
} | |
} | |
controls.addEventListener("mouseenter", (e) => { | |
controls.classList.add("show-controls"); | |
isCursorOnControls = true; | |
}); | |
controls.addEventListener("mouseleave", (e) => { | |
isCursorOnControls = false; | |
}); | |
mainState.addEventListener("click", toggleMainState); | |
mainState.addEventListener("animationend", handleMainSateAnimationEnd); | |
muteUnmute.addEventListener("click", toggleMuteUnmute); | |
muteUnmute.addEventListener("mouseenter", (e) => { | |
if (!muted) { | |
totalVol.classList.add("show"); | |
} else { | |
totalVol.classList.remove("show"); | |
} | |
}); | |
muteUnmute.addEventListener("mouseleave", (e) => { | |
if (e.relatedTarget != volume) { | |
totalVol.classList.remove("show"); | |
} | |
}); | |
forward.addEventListener("click", handleForward); | |
forwardSate.addEventListener("animationend", () => { | |
forwardSate.classList.remove("show-state"); | |
forwardSate.classList.remove("animate-state"); | |
}); | |
backward.addEventListener("click", handleBackward); | |
backwardSate.addEventListener("animationend", () => { | |
backwardSate.classList.remove("show-state"); | |
backwardSate.classList.remove("animate-state"); | |
}); | |
miniPlayer.addEventListener("click", toggleMiniPlayer); | |
theaterBtn.addEventListener("click", toggleTheater); | |
settingsBtn.addEventListener("click", handleSettingMenu); | |
speedButtons.forEach((btn) => { | |
btn.addEventListener("click", handlePlaybackRate); | |
}); | |
document.addEventListener("keydown", (e) => { | |
const tagName = document.activeElement.tagName.toLowerCase(); | |
if (tagName === "input") return; | |
if (e.key.match(/[0-9]/gi)) { | |
video.currentTime = (video.duration / 100) * (parseInt(e.key) * 10); | |
currentTime.style.width = parseInt(e.key) * 10 + "%"; | |
} | |
switch (e.key.toLowerCase()) { | |
case " ": | |
if (tagName === "button") return; | |
if (isPlaying) { | |
video.pause(); | |
} else { | |
video.play(); | |
} | |
break; | |
case "f": | |
toggleFullscreen(); | |
break; | |
case "arrowright": | |
handleForward(); | |
break; | |
case "arrowleft": | |
handleBackward(); | |
break; | |
case "t": | |
toggleTheater(); | |
break; | |
case "i": | |
toggleMiniPlayer(); | |
break; | |
case "m": | |
toggleMuteUnmute(); | |
break; | |
case "+": | |
handlePlaybackRateKey("increase"); | |
break; | |
case "-": | |
handlePlaybackRateKey(); | |
break; | |
default: | |
break; | |
} | |
}); | |
function canPlayInit() { | |
totalDuration.innerHTML = showDuration(video.duration); | |
video.volume = volumeVal; | |
muted = video.muted; | |
if (video.paused) { | |
controls.classList.add("show-controls"); | |
mainState.classList.add("show-state"); | |
handleMainStateIcon(`<ion-icon name="play-outline"></ion-icon>`); | |
} | |
} | |
function play() { | |
video.play(); | |
isPlaying = true; | |
playPause.innerHTML = `<ion-icon name="pause-outline"></ion-icon>`; | |
mainState.classList.remove("show-state"); | |
handleMainStateIcon(`<ion-icon name="pause-outline"></ion-icon>`); | |
// watchInterval(); | |
} | |
function watchInterval() { | |
if (isPlaying) { | |
requestAnimationFrame(watchInterval); | |
handleProgressBar(); | |
} | |
} | |
video.ontimeupdate = handleProgressBar; | |
function handleProgressBar() { | |
currentTime.style.width = (video.currentTime / video.duration) * 100 + "%"; | |
currentDuration.innerHTML = showDuration(video.currentTime); | |
} | |
function pause() { | |
video.pause(); | |
isPlaying = false; | |
playPause.innerHTML = `<ion-icon name="play-outline"></ion-icon>`; | |
controls.classList.add("show-controls"); | |
mainState.classList.add("show-state"); | |
handleMainStateIcon(`<ion-icon name="play-outline"></ion-icon>`); | |
if (video.ended) { | |
currentTime.style.width = 100 + "%"; | |
} | |
} | |
function navigate(e) { | |
const totalDurationRect = duration.getBoundingClientRect(); | |
const width = Math.min( | |
Math.max(0, e.clientX - totalDurationRect.x), | |
totalDurationRect.width | |
); | |
currentTime.style.width = (width / totalDurationRect.width) * 100 + "%"; | |
video.currentTime = (width / totalDurationRect.width) * video.duration; | |
} | |
function showDuration(time) { | |
const hours = Math.floor(time / 60 ** 2); | |
const min = Math.floor((time / 60) % 60); | |
const sec = Math.floor(time % 60); | |
if (hours > 0) { | |
return `${formatter(hours)}:${formatter(min)}:${formatter(sec)}`; | |
} else { | |
return `${formatter(min)}:${formatter(sec)}`; | |
} | |
} | |
function formatter(number) { | |
return new Intl.NumberFormat({}, { minimumIntegerDigits: 2 }).format( | |
number | |
); | |
} | |
function toggleMuteUnmute() { | |
if (!muted) { | |
video.volume = 0; | |
muted = true; | |
muteUnmute.innerHTML = `<ion-icon name="volume-mute-outline"></ion-icon>`; | |
handleMainStateIcon(`<ion-icon name="volume-mute-outline"></ion-icon>`); | |
totalVol.classList.remove("show"); | |
} else { | |
video.volume = volumeVal; | |
muted = false; | |
totalVol.classList.add("show"); | |
handleMainStateIcon(`<ion-icon name="volume-high-outline"></ion-icon>`); | |
muteUnmute.innerHTML = `<ion-icon name="volume-high-outline"></ion-icon>`; | |
} | |
} | |
function hideControls() { | |
if (timeout) { | |
clearTimeout(timeout); | |
} | |
timeout = setTimeout(() => { | |
if (isPlaying && !isCursorOnControls) { | |
controls.classList.remove("show-controls"); | |
settingMenu.classList.remove("show-setting-menu"); | |
} | |
}, 1000); | |
} | |
function toggleMainState(e) { | |
e.stopPropagation(); | |
if (!e.path.includes(controls)) { | |
if (!isPlaying) { | |
play(); | |
} else { | |
pause(); | |
} | |
} | |
} | |
function handleVolume(e) { | |
const totalVolRect = totalVol.getBoundingClientRect(); | |
currentVol.style.width = | |
Math.min(Math.max(0, e.clientX - totalVolRect.x), totalVolRect.width) + | |
"px"; | |
volumeVal = Math.min( | |
Math.max(0, (e.clientX - totalVolRect.x) / totalVolRect.width), | |
1 | |
); | |
video.volume = volumeVal; | |
} | |
function handleProgress() { | |
if (!video.buffered || !video.buffered.length) { | |
return; | |
} | |
const width = (video.buffered.end(0) / video.duration) * 100 + "%"; | |
buffer.style.width = width; | |
} | |
function toggleFullscreen() { | |
if (!document.fullscreenElement) { | |
videoContainer.requestFullscreen(); | |
handleMainStateIcon(`<ion-icon name="scan-outline"></ion-icon>`); | |
} else { | |
handleMainStateIcon(` <ion-icon name="contract-outline"></ion-icon>`); | |
document.exitFullscreen(); | |
} | |
} | |
function handleMousemove(e) { | |
if (mouseDownProgress) { | |
e.preventDefault(); | |
navigate(e); | |
} | |
if (mouseDownVol) { | |
handleVolume(e); | |
} | |
if (mouseOverDuration) { | |
const rect = duration.getBoundingClientRect(); | |
const width = Math.min(Math.max(0, e.clientX - rect.x), rect.width); | |
const percent = (width / rect.width) * 100; | |
hoverTime.style.width = width + "px"; | |
hoverDuration.innerHTML = showDuration( | |
(video.duration / 100) * percent | |
); | |
} | |
} | |
function handleForward() { | |
forwardSate.classList.add("show-state"); | |
forwardSate.classList.add("animate-state"); | |
video.currentTime += 5; | |
handleProgressBar(); | |
} | |
function handleBackward() { | |
backwardSate.classList.add("show-state"); | |
backwardSate.classList.add("animate-state"); | |
video.currentTime -= 5; | |
handleProgressBar(); | |
} | |
function handleMainStateIcon(icon) { | |
mainState.classList.add("animate-state"); | |
mainState.innerHTML = icon; | |
} | |
function handleMainSateAnimationEnd() { | |
mainState.classList.remove("animate-state"); | |
if (!isPlaying) { | |
mainState.innerHTML = `<ion-icon name="play-outline"></ion-icon>`; | |
} | |
if (document.pictureInPictureElement) { | |
mainState.innerHTML = ` <ion-icon name="tv-outline"></ion-icon>`; | |
} | |
} | |
function toggleTheater() { | |
videoContainer.classList.toggle("theater"); | |
if (videoContainer.classList.contains("theater")) { | |
handleMainStateIcon( | |
`<ion-icon name="tablet-landscape-outline"></ion-icon>` | |
); | |
} else { | |
handleMainStateIcon(`<ion-icon name="tv-outline"></ion-icon>`); | |
} | |
} | |
function toggleMiniPlayer() { | |
if (document.pictureInPictureElement) { | |
document.exitPictureInPicture(); | |
handleMainStateIcon(`<ion-icon name="magnet-outline"></ion-icon>`); | |
} else { | |
video.requestPictureInPicture(); | |
handleMainStateIcon(`<ion-icon name="albums-outline"></ion-icon>`); | |
} | |
} | |
function handleSettingMenu() { | |
settingMenu.classList.toggle("show-setting-menu"); | |
} | |
function handlePlaybackRate(e) { | |
video.playbackRate = parseFloat(e.target.dataset.value); | |
speedButtons.forEach((btn) => { | |
btn.classList.remove("speed-active"); | |
}); | |
e.target.classList.add("speed-active"); | |
settingMenu.classList.remove("show-setting-menu"); | |
} | |
function handlePlaybackRateKey(type = "") { | |
if (type === "increase" && video.playbackRate < 2) { | |
video.playbackRate += 0.25; | |
} else if (video.playbackRate > 0.25 && type !== "increase") { | |
video.playbackRate -= 0.25; | |
} | |
handleMainStateIcon( | |
`<span style="font-size: 1.4rem">${video.playbackRate}x</span>` | |
); | |
speedButtons.forEach((btn) => { | |
btn.classList.remove("speed-active"); | |
if (btn.dataset.value == video.playbackRate) { | |
btn.classList.add("speed-active"); | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment