Video timeline thumbnail · Flowplayer
<head/>
<style>
.flowplayer canvas {
outline: 4px solid #fff;
position: absolute;
z-index: 9999;
display: none;
}
<script>
flowplayer(function (api, root) {
api.bind('ready', function (e, api, video) {
var thumbheight = Math.round(root.height() / 8);
root.append($('<canvas/>').attr({
height: thumbheight,
width: Math.round(thumbheight * video.width / video.height)
}));
});
});
$(function() {
var withThumbnail = function(fpVideo, callback) {
var thumb = $('video.fp-thumbnail');
if (!thumb.length) {
thumb = fpVideo.clone().addClass('fp-thumbnail').appendTo($('body')).css({
position: 'absolute',
left: -9999
}).on('loadedmetadata', function() {
callback(thumb);
});
thumb[0].load();
} else if (thumb[0].readyState !== 4) {
thumb.on('loadedmetadata', function() {
callback(thumb);
});
} else {
callback(thumb);
}
}
$('.fp-timeline').on('mousemove', function(ev) {
var timelineOffset = $('.fp-timeline').offset(),
percentage = (ev.pageX - timelineOffset.left) / $('.fp-timeline').width(),
canv = $('.flowplayer canvas'),
canvWidth = canv.width(),
canvHeight = canv.height(),
fpVideo = $('.flowplayer video');
canv.show().css({
left: Math.round(ev.pageX - (flowplayer().isFullscreen ? canvWidth / 2 : canvWidth + 4 * 2)),
bottom: Math.round($('.flowplayer .fp-controls').height() + 4 * 2)
});
withThumbnail(fpVideo, function(thumb) {
thumb[0].currentTime = fpVideo[0].duration * percentage;
thumb.one('seeked', function() {
var canvas = canv[0];
var ctx = canvas.getContext('2d');
ctx.drawImage(thumb[0], 0, 0, canvWidth, canvHeight);
});
})
}).on('mouseleave', function() {
$('.flowplayer canvas').hide();
});
});