injecting and playing html5 video without flickering - javascript

I'm preloading a video in the background and at a certain point I would like to inject it into the dom and immediately play it without this annoying flickr / repaint / reflow thats going on for a split second. Is there anything I can do to fix this. I'm providing a test case showing an image and video doing the same thing to demonstrate the difference. The image displays smooth and the video displays rather harsh. (Oh, i've testing this on safari and chrome and issue is pretty similar)
http://jsfiddle.net/1d0tcae3/1/
// preloading video
var $video = $('<video />').attr({
'width': '400',
'height': '233',
}).append($('<source />').attr({
'src': "http://dev.davidsalazar.com/videos/pugpie.com/test.mp4",
'type': "video/mp4"
})).css('visibility', 'hidden');
// preloading image
var $image = $('<img />').attr({
'src': 'http://pugpie.davidsalazar.com/assets/uploads/img/22b5f827b29eebf03edded92f5c8b11b.gif',
'width': '404',
'height': '416'
}).css('visibility', 'hidden');
$('#showplay-video').on('click', function(e) {
e.preventDefault();
$video.on('play', function() {
// is there any other event or hackery i could possibly use to make this video play without the browser repainting / reflowing so harshly when playing the video
$video.css('visibility', 'visible')
});
$('#video').html($video);
$video[0].play();
});
$('#showplay-image').on('click', function(e) {
e.preventDefault();
$('#image').html($image);
$image.css('visibility', 'visible');
});

Use the canplay event instead of play to display the video - see MDN.
This fires when enough of the video has buffered for it to be played, so you do not get the black screen showing while it is buffering up - http://jsfiddle.net/1d0tcae3/2/
$video.on('canplay', function() {
$video.css('visibility', 'visible')
});

Related

HTML/CSS/JS Show gif on hover, what exactly is a gif?

I have many div elements that I pull and each of them have a background-image. Some elements however represent a gif and when I mouse hover over them I wish to play the gif and have it stop or reset when the mouse exit.
I see many examples of gif animation with an image tag but I cannot seem to get it to work with a background-image.
So for each Image I have the starting image for the gif as well as the .gif extension to the full content.
I am reading this question here for reference: Start GIF On Mouse Hover and Pause Otherwise?
which brings me to my question: what is a gif?
Is it a collection of smaller images for the "animation"? I see alot of "image slicing" terminology or having multiple images that cycle through to simulate the animation. But is it possible to show a gif through html/css/js with just the starting image and the .gif url?
$container.on('mouseenter', ".gif", function (event) {
var target = event.target;
var $target = $(target);
//play gif
$target.css("background-image", "url(" + theGIFurl + ")");
});
.item gif{
background-image: url(theJPGurl); /
}
A gif is a type of bitmap image. It used to be very popular, because it can have transparent pixels (in contrast to jpg). But in that regard it is replaced by png, which is generally smaller, supports alpha transparency (where gif pixels are either fully transparent or fully opaque), and most importantly, gif images are limited to 256 colors.
One other feat of gif images is their animation. You may know them from old websites that show a rotating envelope or something.
An animated gif image is just a collection of images combined in a single file. Such a file also contains additional timing information in the file. However, a gif image is not a smart object that can be controlled. You can't start, stop, pause or speed up a gif image using JavaScript. It just contains frames and can be looped or not, but all that information is in the file.
So, while you can animate using JavaScript or CSS by showing different images, this is a different technique than just showing an animated gif.
So, maybe it's best to investigate other techniques. While gifs are basically very simple, they are also very limited in their use. For instance, you can't reliably time a script to run the end of a gif animation.
-edit-
Apparently you can (in FireFox) pause a gif file.
$container.on('mouseenter', ".gif", function (event) {
var target = event.target;
var $target = $(target);
//play gif
$target.css("background-image", "url(" + theGIFurl + ")");
});
.item gif{
background-image: url(theJPGurl); /
}
$container.on('mouseenter', ".gif", function (event) {
var target = event.target;
var $target = $(target);
//play gif
$target.css("background-image", "url(" + theGIFurl + ")");
});
.item gif{
background-image: url(theJPGurl); /
}
If anyone could comment, I did find this example which solves this:
http://codepen.io/anon/pen/qbqvgy
div {
width: 500px;
height: 500px;
background: url('http://2.bp.blogspot.com/-CmBgofK7QzU/TVj3u3N1h2I/AAAAAAAADN8/OszBhGvvXRU/s640/tumblr_lg7h9gpbtP1qap9qio1_500.jpeg');
}
div:hover {
background: url('https://media.giphy.com/media/V1T2JBmK03OFy/giphy.gifs');
}
<div>
</div>

Play multiple videos when dragged into an area with jquery

I am having a few issues with a script. For a project I have a container, this container has 8 separate thumbnails which when dragged into my container need to play the corresponding video. I have got 90% of the script working but having a few issues with the drag and drop side of things.
When a thumbnail is dragged into the location it is appending the video correctly but the thumbnail then freezes on top of the container... It should revert back, however when you drag another video in, it reverts back but the first stays fixed. Then when another is dragged into the container, this plays on top of my video. I need to tweak my script to simply:
Revert the thumbnail back to it's position.
Remove any current video that is there.
Append the new video.
Autoplay the video if possible.
This is my script:
$(document).ready(function(){
$(".drag").draggable({
revert: true,
containment: "#content"
});
$(".drop").droppable(
{
drop: function (event, ui)
{
var url = $(ui.draggable).attr('videourl');
var oggurl = $(ui.draggable).attr('oggurl');
var $videocontainer = $('#video-container');
var $video = $('#video');
$videocontainer.empty().append('<video id="video" controls width="400" height="300"><source src="'+url+'" type="video/mp4" /><source src="'+oggurl+'" type="video/ogg" /></video>');
$video.get(0).play();
}
});
});
My jsfiddle is here:
http://jsfiddle.net/9tny5eh6/5/
Many thanks in advance.
Here's the fiddle:
http://jsfiddle.net/karanmhatre/9tny5eh6/6/
JS
$(".drop").droppable(
{
drop: function (event, ui)
{
$(".drag").animate({
top: "0px",
left: "0px"
});
var url = $(ui.draggable).attr('videourl');
var oggurl = $(ui.draggable).attr('oggurl');
var $videocontainer = $('#video-container');
$videocontainer.empty().append('<video id="video" controls width="400" height="300"><source src="'+url+'" type="video/mp4" /><source src="'+oggurl+'" type="video/ogg" /></video>');
$('#video').get(0).play();
}
});
In the drop event, move all .drag elements to the original place using animate. Then, use $('#video') selector to select the video AFTER you have added it to the DOM.
The problem with your solution was that you were referencing the #video object from the DOM when it wasn't even present.
Revert the thumbnail back to it's position. - Done
Remove any current video that is there. - Done
Append the new video. - Done
Autoplay the video if possible. - Done
As mentioned in your scenario, You don't need to drop the element.You can just use drag function and check the coordinate positions.If the coordinate positions lie in the container then you play the video else not

Embed Facebook video via ajax - Resize Issue

For a video gallery, I'm using AJAX to load videos from different video hosts like FB, Youtube, Vimeo etc. I'm embedding the FB video like as mentioned in https://developers.facebook.com/docs/plugins/embedded-video-player using FB's JS SDK.
The problem is that when I'm requesting the FB video via AJAX the video is resizing to a smaller dimension like this:
No issues when the page is fully reloaded(without AJAX).
The JS snippet:
$.ajax({
url: "index.php?gallery&type=fbVideoCode&url=" + url,
success: function(response) {
response = $.trim(response);
$('span.carousel').replaceWith(response);
FB.XFBML.parse(); // To re-parse all FB videos on the page
}
});
Please help.
Thanks in advance.
The problem was with a CSS of a carousel that I was using.
Posting the FB video code for others :-)
PHP: (used for AJAX requests)
function getFBEmbedPlayer($video_id, $width = 600) {
return "<div class=\"fb-video\" data-href=\"https://www.facebook.com/video.php?v=$video_id\" data-width=\"$width\">
<div class = \"fb-xfbml-parse-ignore\"></div></div>";
}
JS:
Follow the instructions in https://developers.facebook.com/docs/plugins/embedded-video-player
This will make all videos from Youtube and Vimeo responsive:
// Find all YouTube videos
var $allVideos = $("iframe[src^='//player.vimeo.com'], iframe[src^='//www.youtube.com']"),
// The element that is fluid width
$fluidEl = $("body");
// Figure out and save aspect ratio for each video
$allVideos.each(function() {
$(this)
.data('aspectRatio', this.height / this.width)
// and remove the hard coded width/height
.removeAttr('height')
.removeAttr('width');
});
// When the window is resized
$(window).resize(function() {
var newWidth = $fluidEl.width();
// Resize all videos according to their own aspect ratio
$allVideos.each(function() {
var $el = $(this);
$el
.width(newWidth)
.height(newWidth * $el.data('aspectRatio'));
});
// Kick off one resize to fix all videos on page load
}).resize();
Taken from Chris Coyiers tutorial

Prevent an HTML5 video from playing when the play button is paused

I have a video embedded in a site, and when a user plays the video I have JS to expand the video to the width of the site (and then shrink it on pause).
The video is being played/paused using the built-in controls, but when the video plays while expanding, it just looks weird, hence my desire to prevent playing until after the expansion.
However, preventDefault(); doesn't seem to be working in this instance. Does anyone know a way of achieving this? Thanks.
Here is my JS -
$(document).ready(function(){
var video = $('#intro-video');
video.on('play', function(e){
e.preventDefault();
video.animate({
height: '506',
width: '900'
}, 500);
});
video.on('pause', function(e){
video.animate({
height: '200',
width: '356'
}, 500);
});
});
And here is the HTML source -
<video id="intro-video" controls="">
<source type="video/mp4" src="http://www.somesite.com/video.mp4"></source>
Sorry, your browser is old and doesn't support the HTML5 'video' tag. Sucks to be you...
</video>
Because you're using the inbuilt player controls, the video will start when you press play, and I don't believe you can prevent the event at this point in javascript.
I would recommend looking into creating your own controls for the player. That way, you can listen for the click event on the play button, and control the playback for the video directly.
Otherwise, the only thing I can think of is what I've done here: JSFiddle
Basically, when the video starts to play, pause it. Do the animation, then play it once the animation's finished. I've created a variable so the pause animation doesn't get triggered when we manually pause it:
var video = $('#intro-video');
var enlarged = false;
video.on('play', function(e){
if (!enlarged){
video[0].pause();
video.animate({
height: '506',
width: '900'
}, 500, function() {
enlarged = true;
video[0].play();
});
}
});
video.on('pause', function(e){
if (enlarged) {
enlarged = false;
video.animate({
height: '200',
width: '356'
}, 500);
}
});
Actually it's very simple:
let videoShouldNotPlay = true
video.onplay = function () {
if (videoShouldNotPlay) {
video.pause()
video.currentTime = 0 // set to the current time needed
alert("You can't play the video right now")
return
}
}

fade HTML5 video image / poster in and out

Is it possible to fade out the HTML5 video poster / oimage if we start the video and fade it in again when we pause or stop the video?
Normally the poster image is directly hidden when the video is started and also directly shown when we load the video / stop it
Maybe we can clone the poster image to a canvas, position it over the video and fade it out and in?
Is there an existing solution / script?
The behavior of the poster attribute is really driven by the <video> tag itself. You're just telling it, before starting display this image. Like any video element customization, this would require you to have your own elements involved. Basically, you would have:
<div class="video-container" style="position:relative">
<video width="x" height="y"></video>
<img style="position: absolute; top: 0; left: 0; bottom: 0; right: 0">
</div>
You would then have to bind your events, for example with Zepto:
$('.video-container img').bind('click', function() {
var $img = $(this),
$vid = $img.parent().find('video');
$img.animate({opacity: 0}, 1000, 'linear', function() {
$img.css({visibility: 'hidden'});
$vid[0].play();
});
});
Similarly, you would listen for the pause event and when it occurs fade back in.
That said, this is probably a bad idea for two reasons:
This probably won't work for iOS or any device that prevents scripted playback. In these devices, you can only trigger play() when inside a click event handler. Since you're playing a second later, you don't really have control.
You're breaking default functionality. When I pause a video, I may want to seek to another moment but I definitely want to know where I left off. The lack of a visual queue takes that away.
Update
Here's a different approach that would help you get around the iOS difficulties. In this case, you actually start the video on click, meaning there will be a period of time where the fading image covers the playing video, so it's your call.
$('.video-container').each(function() {
var $img = $(this).find('img'),
$vid = $(this).find('vid');
$img.bind('click', function() { $vid[0].play() });
$vid.bind('play', function() {
$img.animate({opacity: 0}, 1000, 'linear', function() {
if($vid[0].playing) {
$img.css({visibility: 'hidden'});
}
});
});
$vid.bind('pause ended', function() {
$img.css({visibility: 'visible'});
$img.animate({opacity: 1}, 1000, 'linear');
});
});

Categories