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');
});
});
Related
functionality:
User is able to access the video page from the main menu. Video will be played automatically, at this moment, the video is not in full screen and for aesthetic purposes, there are no control buttons in the video frame.
Secondly, when user clicks on the video, it will be displayed as full-screen, and when user clicks on the full-screen video, the video will exit the full screen and reverts back to the original video frame size.
What has been done:
I have created the video frame by using the jQuery .jPlayer. And the video is playing automatically when the video page is loaded.
I have attached the following code:
function Footprints() {
console.log("Footprints");
//Main video player for video page
$("#Footprints_1").jPlayer({
ready: function() {},
swfPath: "javascript",
supplied: "webmv, ogv, m4v",
loop: true,
size: {
width: 1450,
height: 750
}
}).bind($.jPlayer.event.play, function() { // pause other instances of player when current one play
$(this).jPlayer("pauseOthers");
});
$("#Footprints_1").jPlayer("setMedia", {
//set m4v tag to array Footprints VideoList
m4v: "http://www.jplayer.org/video/m4v/Finding_Nemo_Teaser.m4v"
}).jPlayer("play");
$("#Footprints_1").show();
$("Footprints_1").click(function() {
console.log("fullscreen")
$("#Footprints_1").requestFullscreen();
})
}
<div id="Footprints_Page" align="center" style="position:absolute; background-repeat: no-repeat; display: none; top:0px; left:0px; ">
<!--Video Player-->
<div id="Footprints_1" style="position:absolute; top: 180px;"></div>
</div>
Hence, when you run the code, it is showing this:
Issue:
At this point, when I click on the video frame when the video is playing, nothing happens. The video doesn't expand to the full screen.
Hence, how am I able to make the video expand to full screen when I click on the video and and when the video is clicked it reverts back to the original size.
Thanks.
You are currently fighting two three issues.
The first is you are not using jplayer's event system. that is why the clicks are being ignored.
I added a bind.click to your jplayer decleration, and the clicks responded.
.bind($.jPlayer.event.click, function() {
console.log("fullscreen")
$("#Footprints_1").requestFullscreen();
});
See this Fiddle.
The second issue is that you are calling requestFullscreen() on a jQuery object. It is not part of the jQuery API. You need to be calling it on an HTML element.
document.getElementById("jp_video_0").requestFullscreen();
So, the above example should probably be: (untested)
.bind($.jPlayer.event.click, function() {
console.log("fullscreen")
document.getElementById("jp_video_0").requestFullscreen();
});
If you want to have some control over padding and placement, request fullscreen on the container, and you can use CSS.
document.getElementById("Footprints_1").requestFullscreen();
However, the third issue is that not all browsers seem to use the same method of requestFullscreen(). See Mozilla docs. For me the following worked in Chrome:
.bind($.jPlayer.event.click, function() {
console.log("fullscreen")
var elem = document.getElementById("Footprints_1");
if (elem.requestFullscreen) {
elem.requestFullscreen();
} else if (elem.msRequestFullscreen) {
elem.msRequestFullscreen();
} else if (elem.mozRequestFullScreen) {
elem.mozRequestFullScreen();
} else if (elem.webkitRequestFullscreen) {
elem.webkitRequestFullscreen();
}
})
This Post has more info on fullscreen from jQuery as well as info on x-browser issues.
Hope it helps.
Edit: jsFiddle can't demonstrate the Fullscreen API, because I can not add the required 'AllowFullscreen' attribute to their iframe. If you view the frame source of the jsFiddle result, you can just save that as an HTML document, and it should work.
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')
});
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
}
}
I'm using the vimeo api to slide a video off the screen after it finishes playing. Underneath the video player, hidden, I have an image that says 'replay'. The image though is slightly bigger than the player so I want to hide the image via .hide() or display: none in the css and then show it after the animation of the video player completes.
Here's my js:
$(document).ready(function() {
$(".vimeo-container img").hide();
$('iframe.vimeo').each(function(){
Froogaloop(this).addEvent('ready', ready);
});
function ready(playerID){
Froogaloop(playerID).addEvent('finish', onFinish);
}
function onFinish(playerID) {
var player = "#" + playerID;
$(player).animate({width: "0%"}, 750, function() {
$(player).next("img").show();
});
}
});
So the first line is hiding the image. And then when the onFinish function completes I'm trying to show() the image, but it won't work. I should note that when I reverse it and do:
$(player).next("img").hide();
it works.
Here's my HTML:
%section#container1
.row.video-left
.large-8.columns
.vimeo-container
.flex-video.widescreen.vimeo
%iframe.vimeo#player1{allowfullscreen: "", frameborder: "0", height: "225", mozallowfullscreen: "", src: "http://player.vimeo.com/video/60122989?api=1&player_id=player1", webkitallowfullscreen: "", width: "400"}
= image_tag "behind1.png", class: "behind1"
And CSS:
.vimeo-container {
position: relative;
.behind1 {
margin-top: -27em;
}
I've also tried setting display: none in the css, but that wont work either. Not sure what I'm missing.
Thanks.
EDIT
function onFinish(playerID) {
var player = "#" + playerID;
$(player).animate({width: "0%"}, 750, function() {
console.log($(player));
$(player).next().show();
});
}
When I log out ($(player) it returns:
And when I log out console.log($(player).next()); it logs out the image that I am trying to show.
According to the jQuery documentation on the animate method here:
Note: Unlike shorthand animation methods such as .slideDown() and .fadeIn(), the .animate() method does not make hidden elements visible as part of the effect. For example, given $( "someElement" ).hide().animate({height: "20px"}, 500), the animation will run, but the element will remain hidden.
I had a similar need in a project and what worked for me there was to set the z-index of the element I wanted to hide to be less than that of the background. Then, when I wanted to show (or, in your case, animate) I could apply the jQuery methods to the element as if they were hidden (by increasing the z-index so that the element becomes visible), yet not incur the undefined behaviour of attempting to manipulate a hidden element.
Another option would be to move the element off the screen by way of a negative (x, y) coordinate and work from there. I'm not sure which visually would be more appealing in your use case but mention it for completeness.
I have this code:
$('.pic_windows img').mouseenter(function () {
$(this).effect('shake', {
times : 4,
distance : 5
}, 15).attr('src', $(this).attr('src').replace(/.jpg/, '-1.jpg'))
});
$('.pic_windows img').mouseleave(function () {
$(this).attr('src', $(this).attr('src').replace(/-1.jpg/, '.jpg'))
});
where I'm using JQuery's .attr to swap the images, but I'd like the swapping to occur over the course of around 1 second. I've googled this and get all these complicated "CSS3 transitions with JQuery fallback" tutorials. Is there a way to 'animate' an .attr change?
I think I should do a fadeOut while the other fadeIn but I don't know how to write it, as I'm almost a complete JQuery newbie. I have a number of these transitions to do over the course of several pages. It'd be a cinch if I needed to write this for just one instance.
UPDATE On mouseenter, the image shakes and then should during this shake, fade from one picture to its swapped picture. On mouseleave, the image should just fade back to the original picture. Unfortunately I have also found that the shake effect is breaking on IE, all versions, as well as the image swap (it doesn't see image 2 at all)
No, you cannot animate an attribute change. What you can do is clone an element, change an attribute and transition between them.
var target = $(this).fadeOut();
var src = target.attr('src').replace(/-1.jpg/, '.jpg');
var copy = target.clone()
.attr('src', src)
.hide()
.insertAfter(target)
.fadeIn();
EDIT: Thank you for clarifying your intentions, I would advise not playing with the 'src', which will essentially require building a small stateful plugin. Instead, stick with the desired effect here, reveal an image on hover. jsFiddle
HTML
<div class="shaker">
<img src="http://lorempixel.com/output/nature-q-c-360-240-3.jpg" />
<img class="hover" src="http://lorempixel.com/output/technics-q-c-360-240-9.jpg" />
</div>
CSS
.shaker {
position: relative;
}
.shaker img {
position: absolute;
}
.hover {
display: none;
}
JS
$('.shaker').hover(function () {
$(this).effect('shake', {
times: 4,
distance: 5
}, 15);
$(this).find('.hover').fadeIn();
}, function () {
$(this).find('.hover').stop().fadeOut();
});
http://jsfiddle.net/eHQ3t/13/