18
How I customized a video Player + bonus(fullscreen video)
Hi everyone 👋!
How are you doing?
Today I will show you how I did the JavaScript30 - Wes Bos challenge of customizing a video player.
The challenge was only to customize the controls player of the video, but Wes Bos suggested in the final minutes of the video to try to add a button for fullscreen. So I searched and found a fullscreen API to use in my project.
Let me show since the beggining
First I did the HTML
- Created a div with class name "player".Inside I added the video tag and another div for controls.
<div class="player">
<video class="player__video" src="./1003935.mp4"></video>
<div class="player__controls">
</div>
</div>
Inside the player Controls I added the tags for the player button, volume input, speed input, backwards button, forwards button and fullscreen button.
<div class="player__controls">
<!--progress Bar-->
<div class="progress">
<div class="progress__filled"></div>
</div>
<!--player Button-->
<div class="player__Button toggle" tittle="Toggle Play">►</div>
<!--volume input range-->
<input class="player__slider" type="range" name="speed" value="1" min="0.5" max="2" step="0.1">
<!--speed input range -->
<input class="player__slider" type="range" name="speed" value="1" min="0.5" max="2" step="0.1">
<!--backwards and forwards buttons-->
<button class="player__button" data-skip="-10">« 10s </button>
<button class="player__button" data-skip="20">25s » </button>
<!--fullscreen button-->
<button class="fullscreen__button">
<i class="fas fa-compress"></i>
</button>
</div>
2.Added the CSS styles ( you can check here )
3.Finally I did the JavaScript to make this video player functional
First I obtained the elements
const player = document.querySelector('.player')
const video = player.querySelector('.player__video')
const progress = player.querySelector('.progress')
const progressbar = player.querySelector('.progress__filled')
const playerButton = player.querySelector('.toggle')
const ranges = player.querySelectorAll('.player__slider')
const skipButtons = player.querySelectorAll('[data-skip]')
const fullScreenBtn = player.querySelector('.fullscreen__button')
Then I made the events and functions for each functionality of the video player:
- For the video I created a toggle play/pause the video my clicking in the video. I did a event listener to the video variable with click event and a function called togglePlay. That function does a if statement that plays the video if the video is paaused and pauses the video if the video is playing.
const togglePlay = function(){
if(video.paused){
video.play()
}else{
video.pause()
}
}
video.addEventListener('click', togglePlay)
- After that, I needed to update the icon play to pause and pause to play while we click on video. So I added 2 other event Listeners to video variable , one with play event and other with pause event and both with function called updateButton.
const updateButton = function(){
const icon = this.paused ? '►' : '❚❚'
playerButton.textContent = icon
}
video.addEventListener('play',updateButton)
video.addEventListener('pause',updateButton)
- for the player button I added an event listener to the playerButton variable with click event and a function togglePlay created before for the video that plays the video if its paused and paused if its playing , and because we created a a video event listener with event play and pause it will update the icon even clicking by the player button.
playerButton.addEventListener('click', togglePlay)
- For the Skip Buttons I made a forEach loop to add a event listener for each button with click event and a function called skip. In the function skip we add addition assignment the current time of the video to the value of the data-set called skip of the current element clicked(this). We had to envolve into parseFloat because the value it comes as a string and ewe need in JavaScript to be a number.
const skip = function(){
video.currentTime += parseFloat(this.dataset.skip)
}
skipButtons.forEach( button => button.addEventListener('click', skip)
- For updating the range inputs - volume and speed I made a forEach for each range element ,added two events : change and mousemove and a function called handleRangeUpdate. The function takes the video and add the name attribute of the current range used ([this.name] is the same has[volume] or [speed]) and assign the value of the current range is used ( this.value - the value of ther attribute value that changes by the event change or mousemove).
const handleRangeUpdate = function(){
video[this.name] = this.value
}
ranges.forEach( range => range.addEventListener('change', handleRangeUpdate)
ranges.forEach( range => range.addEventListener( 'mousemove', handleRangeUpdate)
- After this I took care of the progress Bar. First I created other event lister to video variable with timeupdate event and a function called handleProgress. This function is responsable to fullfill the progress Bar by playing the video. First I needed to to some Math to get the division of video current time with video duration. this result must be multiplied by 100 to get the percent. Then we put this result at the style of flexBasis of the progressBar class that exist in CSS. Remember it is a string so I needed to use template strings to add the result and the % symbol in the end.
const handleProgress = function(){
const percent=(video.currentTime / video.duration)*100
progressBar.style.flexBasis = `${percent}%`
}
video.addEventListener('timeupdate', handleProgress)
- After that I also had to update the video and the progress bar by clicking and moving over the progress bar. the final resul is to move the progress bar forwards or backwards with the mouse, updating the video in the place where we moved the Progress Bar. So first I created a variable called mousedown with a boolean false. then took the progress and add an event listener with click event and function named scrub. Added another event to progress with mousemove event with anonymous function.Inside that function e make a if statement if the mouse is down and then call the scrub function .
the function scrub is responsable to do a math that takes the offsetX of event divided to the progress offsetWidth ,multiplying the result for video duration. then assign this result to currentTime Video.
Then add two events to progressBar , one is mousedown the other mouseup. first event when is mousedown the mousedown variable takes true mouseup the variable mousedown takes false again.
const scrub = function(e){
const scrubTime = (e.offsetX / progress.offsetWidth) * video.duration
video.currentTime = scrubTime
}
let mousedown = false
progress.addEventListener('click', scrub)
progress.addEventListenr('mousemove', (e) =>{
if(mousedown){
scrub(e)
}
})
progressBar.addEventListener('mousedown', () => mousedown = true)
progressBar.addEventListener('mouseup', () => mousedown = false)
- Finally I did the last piece to finish this challenge which was the fullscreen video. I made a research and found out in MDN tha there is an API already implemented in JavaScript. I followed the explication and what I did was, first add an event listener to the fullscreen button with click event and a function called fullScreen In the fullScreen function I just neeed to do a if statement that if the video requests full screen then call the method resquestFullScreen() to the video.
function fullScreen(){
if(video.requestFullscreen){
video.requestFullscreen()
}
}
fullScreenBtn.addEventListener('click',fullScreen)
18