HTML5 Video play once scrolled into view. - javascript

I've got some fullscreen video backgrounds that I want to play once they're scrolled into view.
The code I'm using for the video running is as follows.
<video id="video_background" preload="false" autoplay="false" loop="loop" volume="0"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> Video not supported </video>
The full-screen side works great, the video plays and I'm very happy with how it all looks but I've got a couple of issues.
Even at the point I'm at, the video isn't taking into account the autoplay="false" attribute. It's instantly playing as soon as the page loads.
Can someone point me in the right direction to play html5 video when the section is scrolled into view? I'm using sections such as the following for each bit.
<div class="container"><video id="video_background" preload="false" autoplay="false" loop="loop" volume="0"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> Video not supported </video></div></section>
I can't find anything that will let me start a section when it scrolls into view.
Any ideas?

According to w3schools.com the autoplay must be coded just if you want autoplay, and ignore if you don't want autoplay.
To know when some element appears in the viewport yo can use jquery.appear plugin:
$('someselector').on('appear', function(event, $all_appeared_elements) {
// this element is now inside browser viewport: play video
});
$('someselector').on('disappear', function(event, $all_disappeared_elements) {
// this element is now outside browser viewpor: Pause/stop video?
});
If you don't want to use this jQuery plugin, in this StackOverflow question the accepted response to know where some element is scrolled into view is:
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}

Related

Executing a function ? works only on resize

I'm trying to make a div the same height of a video on my website.
so I executed this:
var videoHeight = 0;
videoHeight = $("video").css("height");
$(".tester").css("height", videoHeight);
in
$(document).ready(function(){}
and in
$(window).resize(function(){}
but the height is only accurate when I resize the window, not on refresh. What should I do ?
when refreshing : the video is 554 pixels high and my div 493 pixels
when resizing : it is equal
Any ideas ?
EDIT:
Here is my video tag:
<video class="video" preload="auto" loop="loop" controls>
<source src="video/demo.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
Maybe it'll work like this:
video.addEventListener('loadedmetadata', function() {
// Video is loaded and can be played
var videoHeight = 0;
videoHeight = $("video").css("height");
$(".tester").css("height", videoHeight);
}, false);
Wait until an HTML5 video loads
The video does not know its dimensions until metadata is loaded. Use https://developer.mozilla.org/en-US/docs/Web/Events/loadedmetadata
video.addEventListener('loadedmetadata', function() {
var videoHeight = $("video").css("height");
$(".tester").css("height", videoHeight);
}, false);
Note that the loadedmetadata event may already have fired by the time DOMReady fires so you may need to check the height before setting the handler.

How to stop white "flash" between javascript video re-loads?

I am building a site with a video background. I have some javascript (shown below) which selects the most appropriate video source based on screen size and bandwidth. It starts by showing a default low-res version and then as soon as the bandwidth has been calculated, the highest quality that is appropriate is set as the new element source. However, this means that when the resolution is "upgraded" on the video.load(); command, the background flashes white. Is there a way of getting a less obtrusive transition, something like the video streaming sites changing resolution mid video.
<div class="video-container">
<video autoplay loop mob-hide id="video">
<source src="Images/Medium.mp4" type="video/mp4" />
Your browser does not support the video tag. I suggest you upgrade your browser.</video>
</div>
JS:
var video = document.getElementById('video');
if (screen.width > 992 && screen.width <= 1200) {
console.log(screen.width);
if (speedMbps > 0 && speedMbps <= 5) {
video.setAttribute("src", "Images/Medium.mp4");
}
if (speedMbps > 5 && speedMbps <= 10) {
video.setAttribute("src", "../Images/Large.mp4");
}
//more options etc.
}
video.load();

which is more performant, <video> or <canvas> with video embed?

I am developing a page with a full width / full height intro video (100vw / 100vh), looks "full screen" until you scroll down.
Currently I am using HTML5 <video> to accomplish this, but I've noticed the page can get a little choppy, particularly while scrolling. The video is about 4mb.
Would I see an increase in performance if I were to replace the <video> with a <canvas>, and load the video frames directly through the canvas object instead? both elements are GPU accelerated so I'd figure it shouldn't make a difference, but I'm not sure.
No, all the cost of decoding a video frame is still there. Using a canvas would in addition to that add more cost, not less.
If the video is without sound you could temporary pause the video while scrolling, as well as pause it permanently when out of view:
var vt;
window.onscroll = function() {
video.pause(); // pause video
clearTimeout(vt); // clear timer
vt = setTimeout(function() { // create a new timer
var r = video.getBoudingClientRect(); // abs. bound
if (window.scrollY < r.height) video.play(); // assumes video is in top
}, 70); // 70ms
...
};
Another key, although not of very much difference, is to make sure the video code is easy to decode. You can achieve this by removing noise, use flat colors and large surfaces, good lighting conditions, low depth-of-field to blur background as well as lower contrast and avoid too many details in the main subject(s) (this will also produce smaller files).
var video = document.querySelector("video"),
vt;
window.onscroll = function() {
video.pause();
clearTimeout(vt);
vt = setTimeout(function() {
var r = video.getBoundingClientRect();
if (window.scrollY < r.height) video.play();
}, 70);
};
html, body {width:100%; height: 2000px}
video {
width:100%;
height:auto;
}
<video muted width="500" height="280" autoplay="true">
<source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" type="video/mp4">
<source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.webm" type="video/webm">
<source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.ogv" type="video/ogg">
</video>

Start video at vertical scroll point, then play in reverse

I'm trying to achieve something with html5 video and haven't been able to find an answer elsewhere. Is it possible? Any help is much appreciated.
Here's the html:
<video autoplay="autoplay" poster="http://dummyimage.com/320x240/ffffff/fff">
<source src="videos/ship.mp4" type="video/mp4" />
</video>
I want to:
- on page load, display the video paused on the first frame (use poster?)
- at vertical scroll of X pixels, play the video once through (alternatively, inject it onto the page at X scroll?)
- then, when I scroll back beyond the X pixels value play the video again in reverse once through (does this work aMediaElement.playbackRate = -1; ?)
sadly the simplest solution playbackRate = -1 doesn't seem to be implemented anywhere yet.
you could fake it with some code like below to jump the currentTime back at whatever rate you need but from playing around it doesn't look very smooth.
my suggestion would be - if practical - to actually encode a a reversed version of the video if being able to play it backwards is the goal and then swap the source or toggle the visible <video> tag
Oh, and as usual... any video you're planning to stream on the web make sure you optimize and get the moov atom in the right place (see sample ffmpeg)
<script>
var intervalRewind = 0;
var v = document.getElementById("v")
function rewind() {
intervalRewind = setInterval(
function(){
v.playbackRate = 1.0;
if(v.currentTime == 0){
clearInterval(intervalRewind);
v.pause();
} else {
v.currentTime += -.1;
}
},30);
}
</script>
...
<video id="v" onclick="clearInterval(intervalRewind)" width="320" height="240" controls="controls">
<source type="video/mp4" src="video-fs.mp4" />
</video>
<button onclick="rewind()">Rewind</button>

Touch Events stop working on iPad after the Video tag

I have an application that lets you swipe left and right to view different screens, or alternatively click on the Next and Previous buttons to navigate.
if(isMobile){
detectSwipe = true;
document.addEventListener('touchstart',TouchStart,false);
document.addEventListener('touchmove',TouchMove,false);
document.addEventListener('touchend',TouchEnd,false);
document.addEventListener('touchend',TouchCancel,false);
}
$("#prevBtn").on('touchstart click', function () {
...
}
The problem is for some unknown reason when it reaches a screen with a video tag all buttons become unclickable and only the swipe events are still active. This only happens on the iPad however, on the desktop it works fine.
<video width="960" height="560">
<source src="video.mp4" type="video/mp4"/>
<source src="video.ogg" type="video/ogg"/>
<source src="video.webm" type="video/webm"/>
Your browser does not support the video tag.
</video>
I've also tried to use a embed youtube video instead of the video tag, but the problem persists.
You have to set the video element's controls to false and set your own controls, for it to work.

Categories

Resources