ðĄ ėėęą° & ëģžëĨĻ ėė
click / keydown / input / change / volumechange
const videoContainer = document.querySelector("video-container");
const video = document.querySelector("video");
const videoPlayer = document.querySelector(".video-player");
const playBtn = document.querySelector(".video-player__play");
const muteBtn = document.querySelector(".video-player__mute");
const volumeRange = document.querySelector(".video-player__volume");
const time = document.querySelector(".video-player__time");
const currentTime = document.querySelector(".video-player__currentTime");
const totalTime = document.querySelector(".video-player__totalTime");
const timeline = document.querySelector(".video-player__timeline");
const fullScreen = document.querySelector(".video-player__fullScreen");
let volumeValue = 0.3;
video.volume = volumeValue;
const handlePlayBtnClick = () => {
if (video.paused) {
video.play();
} else {
video.pause();
}
playBtn.innerHTML = video.paused
? "<i class='fas fa-play'></i>"
: "<i class='fas fa-pause'></i>";
};
const handleMuteBtnClick = () => {
if (video.muted) {
video.muted = false;
video.volume = volumeValue;
} else {
video.muted = true;
video.volume = 0;
}
};
const handleVolumeChange = () => {
volumeRange.value = video.volume;
if (video.muted) {
muteBtn.innerHTML = "<i class='fas fa-volume-mute'></i>";
} else {
muteBtn.innerHTML = "<i class='fas fa-volume-up'></i>";
}
};
const handleVolumeValueInput = () => {
if (volumeRange.value === "0") {
video.muted = true;
video.volume = 0;
} else {
video.muted = false;
video.volume = volumeRange.value;
}
};
const handleVolumeValueChange = () => {
volumeValue = video.volume === 0 ? volumeValue : video.volume;
};
const formatTime = (seconds) => {
const min = String(Math.floor(seconds / 60));
const second = String(Math.floor(seconds % 60));
return `${min.padStart(2, "0")}:${second.padStart(2, "0")}`;
};
const handleLoadedMetadata = () => {
currentTime.textContent = formatTime(video.currentTime);
totalTime.textContent = formatTime(video.duration);
timeline.max = video.duration;
};
const handleTimelineChange = () => {
video.currentTime = timeline.value;
};
const handleCurrentTimeUpdate = () => {
currentTime.textContent = formatTime(video.currentTime);
timeline.value = String(Math.floor(video.currentTime));
};
const handleFullScreenClick = () => {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
video.requestFullscreen();
}
fullScreen.innerHTML = document.fullscreenElement
? "<i class='fas fa-compress'></i>"
: "<i class='fas fa-expand'></i>";
};
const handleVideoEnded = () => {
video.currentTime = 0;
playBtn.innerHTML = "<i class='fas fa-play'></i>";
};
const handleKeyDown = (event) => {
const { key } = event;
switch (key) {
case " ":
event.preventDefault();
handlePlayBtnClick();
break;
case "Enter":
event.preventDefault();
handleFullScreenClick();
break;
case "ArrowRight":
event.preventDefault();
video.currentTime += 1;
break;
case "ArrowLeft":
event.preventDefault();
video.currentTime -= 1;
break;
case "m":
event.preventDefault();
handleMuteBtnClick();
handleVolumeChange();
break;
case "ArrowUp":
event.preventDefault();
if (video.volume === 1) {
return;
}
video.volume = (video.volume + 0.1).toFixed(1);
volumeValue = video.volume;
video.muted = false;
break;
case "ArrowDown":
event.preventDefault();
if (video.volume === 0) {
return;
}
video.volume = (video.volume - 0.1).toFixed(1);
volumeValue = video.volume === 0 ? volumeValue : video.volume;
if (video.volume === 0) {
video.muted = true;
}
break;
}
};
playBtn.addEventListener("click", handlePlayBtnClick);
muteBtn.addEventListener("click", handleMuteBtnClick);
video.addEventListener("volumechange", handleVolumeChange);
volumeRange.addEventListener("input", handleVolumeValueInput);
volumeRange.addEventListener("change", handleVolumeValueChange);
video.addEventListener("loadedmetadata", handleLoadedMetadata);
timeline.addEventListener("input", handleTimelineChange);
video.addEventListener("timeupdate", handleCurrentTimeUpdate);
fullScreen.addEventListener("click", handleFullScreenClick);
video.addEventListener("ended", handleVideoEnded);
window.addEventListener("keydown", handleKeyDown);
ðĄ input[type="range"] CSS ėĪíėžë§ (ėķę°)
input íė range ėĪíėž ėė íęļ°_ėŧĪėĪí ėĪíėž / input rangeė ėĪíėž ėķę°íęļ° ė°ļęģ
íėëžėļ & ëģžëĨĻ ë° ėĪíėžė ėė íëĪ.
linear-gradient()
ëĨž ėīėĐíī ė§í ėíĐė ë°ëž ėęđė ëŽëĶŽ íėíëĪ.
// videoPlayer.scss
.video-player {
display: flex;
flex-direction: column;
justify-content: center;
width: 90%;
padding: 1rem 0;
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
}
// timeline (videoPlayer.js ė°ļęģ )
input[type="range"] {
-webkit-appearance: none;
width: 97%;
height: 0.3rem;
border-radius: $border-radius-lg;
background: $color-white;
margin: 0 auto;
cursor: pointer;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 0.8rem;
height: 0.8rem;
border-radius: 50%;
background: $color-light-blue;
cursor: pointer;
}
// controls
.video-player__controls {
display: flex;
justify-content: space-between;
width: 97%;
margin: 0 auto;
margin-top: 1rem;
font-size: $font-small;
.video-player__play button,
.video-player__mute button,
.video-player__fullScreen button {
width: 3rem;
font-size: $font-medium;
color: $color-dark-white;
}
}
.video-player__left-controls {
display: flex;
align-items: center;
.video-player__volume {
width: 4rem;
margin: 0 1rem;
}
.video-player__time {
margin: 0 1rem;
}
}
// videoPlayer.js
const PROGRESSED_COLOR = "rgb(168, 218, 220)"; // $color-light-blue
const LEFT_COLOR = "rgba(241, 250, 238, 0.7)"; // $color-white
let volumeValue = 0.3;
video.volume = volumeValue;
volumeRange.style.background = `linear-gradient(to right, ${PROGRESSED_COLOR} 0%, ${PROGRESSED_COLOR} 30%, ${LEFT_COLOR} 30%, ${LEFT_COLOR} 100%)`;
const setTimelineColor = (inputRangeName) => {
const { value } = inputRangeName;
const gradientValue = (100 / +inputRangeName.max) * +value;
inputRangeName.style.background = `linear-gradient(to right, ${PROGRESSED_COLOR} 0%, ${PROGRESSED_COLOR} ${gradientValue}%, ${LEFT_COLOR} ${gradientValue}%, ${LEFT_COLOR} 100%)`;
};
const handleTimelineValueInput = () => {
video.currentTime = timeline.value;
setTimelineColor(timeline);
};
const handleCurrentTimeUpdate = () => {
currentTime.textContent = formatTime(video.currentTime);
timeline.value = String(Math.floor(video.currentTime));
setTimelineColor(timeline);
};
const handleKeyDown = (event) => {
const { key } = event;
switch (key) {
// ėĪëĩ
case "ArrowRight":
event.preventDefault();
video.currentTime += 1;
setTimelineColor(timeline);
break;
case "ArrowLeft":
event.preventDefault();
video.currentTime -= 1;
setTimelineColor(timeline);
break;
case "m":
event.preventDefault();
handleMuteBtnClick();
handleVolumeChange();
break;
case "ArrowUp":
// ėĪëĩ
setTimelineColor(volumeRange);
break;
case "ArrowDown":
// ėĪëĩ
setTimelineColor(volumeRange);
break;
}
};
timeline.addEventListener("input", handleTimelineValueInput);
video.addEventListener("timeupdate", handleCurrentTimeUpdate);
window.addEventListener("keydown", handleKeyDown);
ėė íėíĻ