<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML5 Video Player</title>
<link rel="stylesheet" href="./styles.css"/>
</head>
<body>
<div class="player">
<video class="player__video viewer">
<source src="https://player.vimeo.com/external/194837908.sd.mp4?s=c350076905b78c67f74d7ee39fdb4fef01d12420&profile_id=164" type="video/mp4">
</video>
<div class="player__controls">
<div class="progress">
<div class="progress__filled"></div>
</div>
<div class="control-set">
<button class="player__button" data-control="play">►</button>
<input type="range" data-control="volume" class="player__slider" min="0" max="1" step="0.1" value="0.5">
<input type="range" data-control="playbackRate" class="player__slider" min="0.5" max="2" step="0.1" value="1">
<button class="player__button" data-time="-10"><< 10s</button>
<button class="player__button" data-time="20">25s >></button>
</div>
</div>
</div>
<script src="./scripts.js"></script>
</body>
</html>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
height: 100vh;
background: #540032;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.player {
position: relative;
overflow: hidden;
}
.player__video {
width: 100%;
}
.player__controls {
display: flex;
flex-wrap: wrap;
width: 100%;
margin-top: -2px;
position: absolute;
z-index: 1;
}
.player:hover .player__controls { transform: translateY(-46px) }
.player__video:hover + .player__controls { transform: translateY(-46px) }
.player__controls:hover { transform: translateY(-46px) }
.player__controls *:hover .player__controls { transform: translateY(-46px) }
.player__controls *:focus { outline: none }
.player__controls > * { flex: 1 }
.progress {
flex-basis: 100%;
background: rgba(0, 0, 0, 0.5);
height: 8px;
color: white;
margin-bottom: 6px;
}
.progress .progress__filled {
background: #E00084;
height: 8px;
}
.control-set {
display: flex;
justify-content: space-between;
align-items: center;
}
.control-set > * { flex: 1 }
.player__button {
background: transparent;
height: 25px;
color: #FFF;
border: none;
}
.player__button[data-control="play"] { margin-right: 20px; }
.player__button:last-of-type { margin-right: 0; }
.player__slider {
flex: 2;
margin-right: 20px;
}
input:focus { outline: none; }
input[type=range] {
-webkit-appearance: none;
height: 6px;
background: #e5e5e5;
border-radius: 20px;
cursor: pointer;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 10px;
width: 10px;
border-radius: 20%;
background: #E00084;
cursor: pointer;
box-shadow: 1px 1px 1px rgba(0, 0, 0, .2);
}
@media screen and (max-width: 650px) {
.player { width: 90vw; }
.player__slider { width: 110px; }
}
const video = document.querySelector('.player__video'),
seeker = document.querySelector('.progress'),
seeker_filled = document.querySelector('.progress__filled'),
playButton = document.querySelector('.player__button[data-control="play"]'),
sliders = document.querySelectorAll('.player__slider'),
skipButtons = document.querySelectorAll('.player__button[data-time]');
let isMouseDown = false;
function handlePlay() {
video.paused ? video.play() : video.pause();
video.paused ? playButton.innerHTML = '►' : playButton.innerHTML = '❚ ❚';
}
function autoSeek() {
let filled_width = seeker.offsetWidth / video.duration * video.currentTime;
seeker_filled.style.width = `${filled_width}px`;
}
function handleSeeker(e) {
video.currentTime = e.offsetX * video.duration / seeker.offsetWidth;
seeker_filled.style.width = `${e.offsetX}px`;
}
function handleSkip() {
video.currentTime += parseFloat(this.dataset.time);
}
function handleSlider() {
video[this.dataset.control] = this.value;
}
video.addEventListener('click', handlePlay);
video.addEventListener('timeupdate', autoSeek);
seeker.addEventListener('click', handleSeeker);
seeker.addEventListener('mousemove', (e) => isMouseDown && handleSeeker(e));
seeker.addEventListener('mousedown', () => isMouseDown = true);
seeker.addEventListener('mouseup', () => isMouseDown = false);
playButton.addEventListener('click', handlePlay);
skipButtons.forEach(skipButton => skipButton.addEventListener('click', handleSkip));
sliders.forEach(slider => {
slider.addEventListener('change', handleSlider);
slider.addEventListener('mousemove', handleSlider);
});