video-player-03
by Nic Fontaine
HTML
<div class='container-vid'>
<video id="myvideo" muted>
<source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
<source src="https://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg">
</video>
<!-- <div class='vid-play'>
<i class="fa fa-play-circle"></i>
</div> -->
<div class='timeline-hover'>
<div class='timeline'>
<div class='timeline-sel'></div>
<div id='timeline-bar' class='timeline-bar'></div>
<div id='timeline-bar-fake' class='timeline-bar-fake'></div>
</div>
</div>
</div>
<div id='demo'>fps: </div>
<ul>
<li>click vid for play/pause</li>
<li>click timeline while pause - stays paused, indicator shows, vid stays</li>
<li>release while paused - indicator hide, vid moves, stays paused</li>
<li>click+drag while paused - indicator & glowbar, vid stays</li>
<li>release - vid moves, idicator & glowbar hide</li>
<li>click to play again - at correct time</li>
<li>onend - timestop goes to 100%</li>
<li>onend - click timeline, release, & vid stays</li>
</ul>
<!-- <script async src="https://use.fontawesome.com/dfe288b4db.js"></script> -->
CSS
:focus {outline:none;}
::-moz-focus-inner {border:0;}
body { font-family: sans-serif; }
.container-vid {
position: relative;
width: 800px;
/*overflow: hidden;*/
}
video {
width: 100%;
display: flex; /* FIXES > 100% + EXTRA HEIGHT ISSUE */
}
.timeline {
position: absolute;
overflow: hidden;
opacity: 0;
width: 100%;
margin: 0;
height: 20px;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.3);
transition: background 0.1s, height 0.05s ease-in-out;
}
.timeline.show {
opacity: 1;
}
.container-vid:hover .timeline {
background: rgba(0,0,0,0.5);
}
.timeline-hover {
position: absolute;
bottom: 0;
right: 0; left: 0;
height: 40px;
}
.timeline-hover:hover {
height: 60px;
}
#timeline-bar {
background: rgba(63,183,166,0.8);
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#3fb2a0+0,09a4a9+100,2a2b30+100 */
background: #3fb2a0; /* Old browsers */
background: -moz-linear-gradient(left, #3fb2a0 0%, #09a4a9 100%, #2a2b30 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(left, #3fb2a0 0%,#09a4a9 100%,#2a2b30 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to right, #3fb2a0 0%,#09a4a9 100%,#2a2b30 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3fb2a0', endColorstr='#2a2b30',GradientType=1 ); /* IE6-9 */
/* box-shadow: inset 2px 2px 7px rgba(255, 255, 255, .3), inset -2px -2px 7px rgba(0, 0, 0, .07); */
border-top: 2px solid rgba(255,255,255,0.2);
border-bottom: 1px solid rgba(0,0,0,0.1);
border-right: 2px solid rgba(255,255,255,0.7);
box-sizing: border-box;
height: 100%;
width: 100%;
opacity: 0.7;
transition: opacity 0.1s;
transform: translateX(-100%);
position: relative;
z-index: 1;
box-shadow: 0 0 5px rgba(0,0,0,0.6);
}
#timeline-bar:after {
position: absolute;
content:"";
top: -2px;
right: 0;
margin-right: -6px;
width:0;
...
JavaScript
/*
BUGS
------
- if target fps is too high, timeline won't move fast enough. need speed as inverse var?
if rAF fps is lowered by browser, [rate] should be increased
- rAF stops when switching tabs but vid does not
- 'onend event is slow, noticeably
*/
var vidConts = document.getElementsByClassName('container-vid');
var vidContsLen = vidConts.length;
// PLAY/PAUSE STATUS CONTAINER FOR EACH VID
var vidsStatus = [];
var vidsWidth = [];
var vidPlayingIndex;
var vid = document.getElementById('myvideo'),
tLine = document.getElementsByClassName('timeline')[0],
demo = document.getElementById('demo');
var vidPlaying = false; // FLAG INSTEAD OF CHECK VID STATUS
var timeWidth = 0; // CALC WIDTH, RAF USES
var timeWidthPrep; // CALC WIDTH WHEN CLICK BUT DON'T UPDATE B/C RAF USES timeWidth
const fps = 30;
var rate; // FRAMES TO MOVE EVERY 1/60 OF A SECOND
var dragging; // TOGGLE TO INDICATE IF DRAGGING TIME ON TIMELINE
var now;
var then = Date.now();
const interval = 1000/fps;
var delta;
var counter = 1;
var first = then;
// GRAB VALUES WHEN VID LOADS/CANPLAY
// THIS RUNS ONCE, vid.oncanplay WOULD RUN EVERY TIME IT'S TIME IS UPDATED
//(NOTE) NEED TO DO FOR EVERY VID
var i = setInterval(function() {
if(vid.readyState > 0) {
var minutes = parseInt(vid.duration / 60, 10);
var seconds = vid.duration % 60;
duration = seconds;
// HIDE UNTIL READY
// (NOTE) REPLACE W/ CLASS LOOP
setTimeout(function() {
tLine.classList.add('show');
},500);
clearInterval(i);
}
}, 200);
// LOOP THROUGH ALL .container-vid - ADD EVENTS
for (var i=0; i<vidContsLen; i++) {
vidsStatus.push(null);
vidsWidth.push(vidConts[i].getElementsByClassName('timeline')[0].clientWidth);
(function(index) {
// CTRL - PLAY/PAUSE EVERY VID
vidConts[i].getElementsByTagName('video')[0].addEventListener('click', function() {
vidToggle(index);
},false);
vidConts[i].getElementsByTagName('video')[0].addEventListener('ended', function() {
...