Last active
October 2, 2016 16:30
-
-
Save davidanton1d/5238a81dd670e65cc9fa9d38bf5a37ee to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Bakground video loop on ios through canvas | |
//Note that jQuery is supposed to be loaded as $j due to non-conflict in the original place | |
/// START VIDEO HANDLING FOR MOBILE | |
/// START VIDEO HANDLING FOR MOBILE | |
/// START VIDEO HANDLING FOR MOBILE | |
var cvpHandlers = { | |
canvasClickHandler: null, | |
videoTimeUpdateHandler: null, | |
videoCanPlayHandler: null, | |
windowResizeHandler: null | |
}; | |
var CanvasVideoPlayer = function(options) { | |
var i; | |
this.options = { | |
framesPerSecond: 25, | |
hideVideo: true, | |
autoplay: false, | |
makeLoop: false, | |
pauseOnClick: true, | |
audio: false, | |
timelineSelector: false, | |
resetOnLastFrame: true | |
}; | |
for (i in options) { | |
this.options[i] = options[i]; | |
} | |
this.video = document.querySelector(this.options.videoSelector); | |
this.canvas = document.querySelector(this.options.canvasSelector); | |
this.timeline = document.querySelector(this.options.timelineSelector); | |
this.timelinePassed = document.querySelector(this.options.timelineSelector + '> div'); | |
if (!this.options.videoSelector || !this.video) { | |
console.error('No "videoSelector" property, or the element is not found'); | |
return; | |
} | |
if (!this.options.canvasSelector || !this.canvas) { | |
console.error('No "canvasSelector" property, or the element is not found'); | |
return; | |
} | |
if (this.options.timelineSelector && !this.timeline) { | |
console.error('Element for the "timelineSelector" selector not found'); | |
return; | |
} | |
if (this.options.timelineSelector && !this.timelinePassed) { | |
console.error('Element for the "timelinePassed" not found'); | |
return; | |
} | |
if (this.options.audio) { | |
if (typeof(this.options.audio) === 'string'){ | |
// Use audio selector from options if specified | |
this.audio = document.querySelectorAll(this.options.audio)[0]; | |
if (!this.audio) { | |
console.error('Element for the "audio" not found'); | |
return; | |
} | |
} else { | |
// Creates audio element which uses same video sources | |
this.audio = document.createElement('audio'); | |
this.audio.innerHTML = this.video.innerHTML; | |
this.video.parentNode.insertBefore(this.audio, this.video); | |
this.audio.load(); | |
} | |
var iOS = /iPad|iPhone|iPod/.test(navigator.platform); | |
if (iOS) { | |
// Autoplay doesn't work with audio on iOS | |
// User have to manually start the audio | |
this.options.autoplay = false; | |
} | |
} | |
// Canvas context | |
this.ctx = this.canvas.getContext('2d'); | |
this.playing = false; | |
this.resizeTimeoutReference = false; | |
this.RESIZE_TIMEOUT = 1000; | |
this.init(); | |
this.bind(); | |
}; | |
CanvasVideoPlayer.prototype.init = function() { | |
this.video.load(); | |
var that = this; | |
this.video.addEventListener('loadeddata', function() { | |
// Video is loaded and can be played | |
that.setCanvasSize(); | |
}, false); | |
this.setCanvasSize(); | |
if (this.options.hideVideo) { | |
this.video.style.display = 'none'; | |
} | |
}; | |
// Used most of the jQuery code for the .offset() method | |
CanvasVideoPlayer.prototype.getOffset = function(elem) { | |
var docElem, rect, doc; | |
if (!elem) { | |
return; | |
} | |
rect = elem.getBoundingClientRect(); | |
// Make sure element is not hidden (display: none) or disconnected | |
if (rect.width || rect.height || elem.getClientRects().length) { | |
doc = elem.ownerDocument; | |
docElem = doc.documentElement; | |
return { | |
top: rect.top + window.pageYOffset - docElem.clientTop, | |
left: rect.left + window.pageXOffset - docElem.clientLeft | |
}; | |
} | |
}; | |
CanvasVideoPlayer.prototype.jumpTo = function(percentage) { | |
this.video.currentTime = this.video.duration * percentage; | |
if (this.options.audio) { | |
this.audio.currentTime = this.audio.duration * percentage; | |
} | |
}; | |
CanvasVideoPlayer.prototype.bind = function() { | |
var self = this; | |
// Playes or pauses video on canvas click | |
if(this.options.pauseOnClick === true){ | |
this.canvas.addEventListener('click', cvpHandlers.canvasClickHandler = function() { | |
self.playPause(); | |
}); | |
} | |
// On every time update draws frame | |
this.video.addEventListener('timeupdate', cvpHandlers.videoTimeUpdateHandler = function() { | |
self.drawFrame(); | |
if (self.options.timelineSelector) { | |
self.updateTimeline(); | |
} | |
}); | |
// Draws first frame | |
this.video.addEventListener('canplay', cvpHandlers.videoCanPlayHandler = function() { | |
self.drawFrame(); | |
}); | |
// To be sure 'canplay' event that isn't already fired | |
if (this.video.readyState >= 2) { | |
self.drawFrame(); | |
} | |
if (self.options.autoplay) { | |
self.play(); | |
} | |
// Click on the video seek video | |
if (self.options.timelineSelector) { | |
this.timeline.addEventListener('click', function(e) { | |
var offset = e.clientX - self.getOffset(self.canvas).left; | |
var percentage = offset / self.timeline.offsetWidth; | |
self.jumpTo(percentage); | |
}); | |
} | |
// Cache canvas size on resize (doing it only once in a second) | |
window.addEventListener('resize', cvpHandlers.windowResizeHandler = function() { | |
clearTimeout(self.resizeTimeoutReference); | |
self.resizeTimeoutReference = setTimeout(function() { | |
$j("canvas.canvas").css({width: "100%", height:"100%"}); | |
self.setCanvasSize(); | |
self.drawFrame(); | |
}, self.RESIZE_TIMEOUT); | |
}); | |
this.unbind = function() { | |
this.canvas.removeEventListener('click', cvpHandlers.canvasClickHandler); | |
this.video.removeEventListener('timeupdate', cvpHandlers.videoTimeUpdateHandler); | |
this.video.removeEventListener('canplay', cvpHandlers.videoCanPlayHandler); | |
window.removeEventListener('resize', cvpHandlers.windowResizeHandler); | |
if (this.options.audio) { | |
this.audio.parentNode.removeChild(this.audio); | |
} | |
}; | |
}; | |
CanvasVideoPlayer.prototype.updateTimeline = function() { | |
var percentage = (this.video.currentTime * 100 / this.video.duration).toFixed(2); | |
this.timelinePassed.style.width = percentage + '%'; | |
}; | |
CanvasVideoPlayer.prototype.setCanvasSize = function() { // * 2 för retina-skärmar | |
this.width = this.canvas.clientWidth * 1; | |
this.height = this.width / 1920 * 1080 * 1; //this.canvas.clientHeight; | |
if(this.height < this.canvas.clientHeight){ | |
console.log("Setting video height from canvas height"); | |
this.height = this.canvas.clientHeight; | |
this.width = this.height / 1920 * 1080; //this.canvas.clientWidth; | |
$j("canvas").css({"width": this.height/1080*1920 + "px", "margin-left": -(this.height/1080*1920 - this.canvas.clientWidth) / 2 + "px"}); | |
}else{ | |
$j("canvas").css({"height": this.width/1920*1080 + "px", "margin-top": -(this.width/1920*1080 - this.canvas.clientHeight) / 2 + "px"}); | |
} | |
//console.log("this.width: " + this.width + ", this.height: " + this.height); | |
// this.width = this.canvas.clientWidth * 2; | |
// this.height = this.canvas.clientHeight * 2; | |
this.canvas.setAttribute('width', this.width * 1.5 * 4); // * 4 för retina-skärmar | |
this.canvas.setAttribute('height', this.height * 1.5 * 4); // * 4 for high pixel density displays | |
this.width = this.width * 1.5 * 4; // * 4 for high pixel density displays | |
this.height = this.height * 1.5 * 4; | |
}; | |
CanvasVideoPlayer.prototype.play = function() { | |
this.lastTime = Date.now(); | |
this.playing = true; | |
this.loop(); | |
if (this.options.audio) { | |
// Resync audio and video | |
this.audio.currentTime = this.video.currentTime; | |
this.audio.play(); | |
} | |
}; | |
CanvasVideoPlayer.prototype.pause = function() { | |
this.playing = false; | |
if (this.options.audio) { | |
this.audio.pause(); | |
} | |
}; | |
CanvasVideoPlayer.prototype.playPause = function() { | |
if (this.playing) { | |
this.pause(); | |
} | |
else { | |
this.play(); | |
} | |
}; | |
CanvasVideoPlayer.prototype.loop = function() { | |
var self = this; | |
var time = Date.now(); | |
var elapsed = (time - this.lastTime) / 1000; | |
// Render | |
if(elapsed >= (1 / this.options.framesPerSecond)) { | |
this.video.currentTime = this.video.currentTime + elapsed; | |
this.lastTime = time; | |
// Resync audio and video if they drift more than 300ms apart | |
if(this.audio && Math.abs(this.audio.currentTime - this.video.currentTime) > .3){ | |
this.audio.currentTime = this.video.currentTime; | |
} | |
} | |
// If we are at the end of the video stop | |
if (this.video.currentTime >= this.video.duration) { | |
if(this.options.makeLoop === false){ | |
this.playing = false; | |
} | |
if (this.options.resetOnLastFrame === true) { | |
this.video.currentTime = 0; | |
} | |
} | |
if (this.playing) { | |
this.animationFrame = requestAnimationFrame(function(){ | |
self.loop(); | |
}); | |
} | |
else { | |
cancelAnimationFrame(this.animationFrame); | |
} | |
}; | |
CanvasVideoPlayer.prototype.drawFrame = function() { | |
this.ctx.drawImage(this.video, 0, 0, this.width, this.height); | |
}; | |
$j(document).ready(function(){ | |
//.mobile-video-image | |
$j(".q_slider>.q_slider_inner>div").prepend('<video class="video" width="1920" height="800" poster="" preload="auto" loop="" autoplay="" muted="" src="http://dev1.sahlsa.se/wp-content/uploads/2016/09/Mora-Hemsida-September-2016-UHD.mp4"><source type="video/mp4" src="http://dev1.sahlsa.se/wp-content/uploads/2016/09/Mora-Hemsida-September-2016-UHD.mp4"></video><canvas class="canvas" width="0" height="0"></canvas>') | |
var isIOS = /iPad|iPhone|iPod/.test(navigator.platform); | |
console.log("isIOS: " + isIOS); | |
$j("body").append("isIOS: " + isIOS); | |
if (isIOS) { | |
window.canvasVideo = new CanvasVideoPlayer({ | |
videoSelector: 'video.video', | |
canvasSelector: 'canvas.canvas', | |
timelineSelector: false, | |
autoplay: true, | |
makeLoop: true, | |
pauseOnClick: false, | |
audio: false | |
}); | |
$j("canvas.canvas").css({width: "100%", height:"100%"}); | |
}else { | |
// Use HTML5 video | |
if(document.querySelectorAll('canvas.canvas').length > 0){ | |
document.querySelectorAll('canvas.canvas')[0].style.display = 'none'; | |
} | |
} | |
}); | |
/// END VIDEO HANDLING FOR MOBILE | |
/// END VIDEO HANDLING FOR MOBILE | |
/// END VIDEO HANDLING FOR MOBILE |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment