The idea came while watching a mandatory training video on bullying in the workplace. I can just hear High School Geoff LOL-ing about a wimp like me have to watch that thing.
But here we are.
The video UI was actually lovely, but it was the progress bar that really caught my attention – or rather the [progress].value. It was a simple gradient going from green to blue that grew as the video continued playing. If only I had this advice in high school…
I already know it’s possible to create the same sort gradient on the
The key line is this:
The max attribute tells us we’re working with 100 as the highest value while the value attribute is starting us out at zero. That makes sense since it allows us to think of the video’s progress in terms of a percentage, where 0% is the start and 100% is the end, and where our initial starting point is 0%.
Styling
I’m definitely not going to get deep into the process of styling the
Now we can hook it up. We’ll assign it a variable and use innerHTML to print the current value inside the label.
const progress = document.getElementById(progress);
const timer = document.getElementById( timer );
function progressLoop() {
setInterval(function () {
progress.value = Math.round((video.currentTime / video.duration) * 100);
timer.innerHTML = Math.round(video.currentTime) + seconds;
});
}
progressLoop();
Hey, that works!
CodePen Embed Fallback
Extra credit would involve converting the timer to display in HH:MM:SS format.
Adding a play button
The fact there there were two UIs going on at the same time sure bugged me. the
Then, hook it up with a function that toggles the video between play and pause on click.
button = document.getElementById( play );
function playPause() {
if ( video.paused ) {
video.play();
button.innerHTML = ??;
}
else {
video.pause();
button.innerHTML = ?;
}
}
button.addEventListener( click, playPause );
video.addEventListener(play, progressLoop);
Hey, it’s still working!
CodePen Embed Fallback
I know it seems weird to take out the rich set of controls that HTML5 offers right out of the box. I probably wouldn’t do that on a real project, but we’re just playing around here.
Cleaning up my ugly spaghetti code
I really want to thank my buddy Neal Fennimore. He took time to look at this with me and offer advice that not only makes the code more legible, but does a much, much better job defining states…
// States
const PAUSED = paused;
const PLAYING = playing;
// Initial state
let state = PAUSED;
…doing a proper check for the state before triggering the progress function while listening for the play, pause and click events…
// Animation loop
function progressLoop() {
if(state === PLAYING) {
progress.value = Math.round( ( video.currentTime / video.duration ) * 100 );
timer.innerHTML = Math.round( video.currentTime ) + seconds;
requestAnimationFrame(progressLoop);
}
}
video.addEventListener(play, onPlay);
video.addEventListener(pause, onPause);
button.addEventListener(click, onClick);
…and even making the animation more performant by replacing setInterval with requestAnimationFrame as you can see highlighted in that same snippet.
Here it is in all its glory!
CodePen Embed Fallback
Oh, and yes: I was working on this while “watching” the training video. And, I aced the quiz at the end, thank you very much. ?