click on a button changes video poster and src attributes
after the click video height becomes 0 - a short period - but enough to produce an ugly effect on entire page
how to avoid this?
note - lorem.mp4 and ipsum.mp4 have the same resolution and dimensions
<video class='vtop' id='player' controls poster='lorem.jpg'>
<source src='lorem.mp4' type='video/mp4'>
</video>
js
var player = $('#player');
$('button').on('click', function(){
player.attr('poster', 'ipsum.jpg');
player.attr('src', 'ipsum.mp4');
player[0].play();
});
I tried your code and add a css file to it and give the video a fix height:
video {
height: 400px;
}
I think it is enough and I don't see any special effect when I click button.
The height is changed because your video player height depends on the video height. And when you change src video player height changes as well. What you need to do, is just specify height for your video tag.
Related
I need to add a overlay of rectangular shape to an object (eg. water bottle) in my html5 video, and then track the object throughout the video.
I already have a txt file which contains the object's positions for each frame throughout the video. So I need to:
draw the rectangular shape on each frame of the html5 video. so when the video is being played, we can see the tracking box moving with the object
the tracking box's movement should be synchronised with the video. so when the user click 'pause', the tracking will pause too.
I just need some general advice on how to approach this problem. Is there javascript package that can draw shapes on videos?
1) With HTML5 video, you can't tell what 'frame' the video is on. Only what the current position is in the video in seconds (i.e. 5.4423 seconds, it can be quite specific). If you know how many frames per second your video has (and it's constant) you can reasonably estimate what frame you are on by multiplying frames by current seconds. Simply use videoElement.currentTime to get the elapsed playback time.
To get the current seconds data throughout playback, use the setInterval function and run it every 40 milliseconds (assuming you have a 25 fps video)
2) In you setInterval callback grab the relevant box position from your data file (based on the elapsed seconds/frames) and update the x and y position of the box using javascript (e.g. element.style.left = x + "px"
The box will stop on pause because the elapsed seconds will stop too. Hint: make the box position absolute and the element containing the video position relative, and the box will move relative to the top left corner of the video.
Hope that helps!
Edit: lay out your html like this:
<div id="videoContainer">
<div id="box"></div>
<video id="videoElement" controls>
<source src="myVideo.mp4 type="video/mp4" />
</video>
</div>
And your CSS:
#videoContainer {
position: relative;
}
#box {
width: 100px;
height: 50px;
background: red;
position: absolute;
left: 0;
top: 0;
}
Currently I'm working on building a solution for having responsive background images set via JavaScript. I am using Picturefill to create cross-browser support.
What do I need? There is an element on my page which needs a pretty little background photo. On the page there is a picture element which loads conditionally images. However I specified one default image source if the browser doesn't have proper picture element support.
With MooTools I check what photo is supposed to show up on domready, on window resize I check my image 'src' again to replace my current picture if needed (with a bigger or smaller one).
In FireFox the picture element replaces the image 'src' in the DOM, it works perfect!
Chrome (and IE) don't replace the image 'src' so my photo will always have the default photo dimensions according to MooTools. However, when you hover over the image 'src' via the Chrome developer tools it does show the correct image source for that media query.
I can get in way too many details but trust me I really need to do it like mentioned above, who want to help me with this? :)
<script>
var Placeholder = $('Placeholder');
var CoverImage = $('MyCover').getElement('img').src;
Placeholder.setStyle('background-image', 'url(' + CoverImage + ')');
var $timer = null;
window.addEvent('resize', function(){
var ResponsiveImage = function(){
var $ResponsiveImage = $('MyCover').getElement('img').src;
$('Placeholder').setStyle('background-image', 'url(' + $ResponsiveImage + ')');
};
clearTimeout($timer);
$timer = ResponsiveImage.delay(250, this);
});
</script>
<picture>
<source media="all and (max-width: 30em)" srcset="1.jpg">
<source media="all and (min-width: 30.063em) and (max-width: 48em)" srcset="2.jpg">
<source media="all and (min-width: 48.063em) and (max-width: 80em)" srcset="3.jpg">
<source media="all and (min-width: 80.063em)" srcset="4.jpg">
<img src="2.jpg">
</picture>
Thanks for the possible solutions, I am very grateful!
Cheers,
Stefan
Perhaps I don't understand exactly what you are trying to do, but instead of trying to use the script to control the dimensions why not use the CSS property background-size: cover; instead? That is what I always use for responsive background images not that it is widely supported by browsers.
You should really look at http://foundation.zurb.com/docs/components/interchange.html.
Maybe you can get the script and adapt it to your case?
First of all your markup:
In picture land you don't need to use min-width and max-width. The first source, that matches is the media query is used:
<picture><source media="(max-width: 30em)" srcset="1.jpg">
<source media="(max-width: 48em)" srcset="2.jpg">
<source media="(max-width: 80em)" srcset="3.jpg">
<source srcset="4.jpg">
<img src="2.jpg"></picture>
Now, what you need is actually the property currentSrc, but be aware it needs to be handled different than the src property, because it is updated, after the image is loaded (so don't use resize, use load).
Fortunately there is already a simple lazySizes plugin called bgset, that does exactly what you need. Here you find a demo and here you find the documentation. Of course you can also check out the source code and build your own.
In case you want to use the plugin your markup changes to something like this:
<div class="lazyload" data-bgset="1.jpg [(max-width: 30em)] | 2.jpg [(max-width: 48em)] | 3.jpg [(max-width: 80em)] | 4.jpg"></div>
I am using the currentSrc property to get the updated image source and it works like a charm! Thanks everyone for the help!
My video is instantiated from markup, with a width and height (dummy values actually).
<video id='ytvidplayer' class='video-js vjs-default-skin' controls autoplay
preload='auto' width='xxx' height='xxx' poster='xxx'
data-setup='{}'>
<source src='xxx' type='video/mp4'>
<source src='xxx' type='video/webm'>
Whoops. Your browser does not Support HTML5 or Flash. Please upgrade your browser.
</video>
I am resizing my video once the page is rendered, to be one third (33%) of the screen size in width. This all works well.
var newHeight
var newWidth
newWidth = $(window).width() * 0.33;
newHeight = newWidth * 0.75;
$('#ytvidplayer').css('height',newHeight);
$('#ytvidplayer').css('width',newWidth);
//set related video div height eual to video height
$('#related_vids_scroller').css('height',newHeight);
var myVideo = videojs('ytvidplayer');
myVideo.width(newWidth).height(newHeight);
Everything works as expected, until I try to go fulslcreen. When the fullscreen button is pressed, the physcial "black" container of the video object goes fulslcreen, but the video stays at the API-resized width and height.
Is this a bug in video.js to not take the API-resized values into account (overriding) them on going fullscreen?
When I do not physically resize the video using the API, and have just the original markup (with a width and height)... fullscreen works fine.
I have tried using 'auto" for with and height in the markup, to try and have the video resize to its container ( a 33% div ), so I don;t have to resize it myself using the api. But on w=auto and h=auto, the video renders with no height, but seems to have the correct width... and it plays.. its just invisible (video progress bar is there tho, and at the correct width (fills the 33% div).
I have tried attaching to window.resize, but have difficulty in resizing the video using API there, is its a "toggle" really.. need to know if I am exiting or entering fullscreen mode... based on that, I need to resize up or down...
Any ideas? Am I over-complicating this?
Setting css width and height on #ytvidplayer will be the problem. #ytvidplayer will either be a video element or a div depending on whether the player has been created at that point. Removing these and only resizing with the API only should work:
$('#ytvidplayer').css('height',newHeight);
$('#ytvidplayer').css('width',newWidth);
I want to place a "PLAY" div above each iframe. I want to do it automatically.
I manage to do that manually but I don't know how to do it with a script , or with css.
Here is my HTML markup :
<ul data-role="listview" id="resultat"></ul>
And my Javascript code :
$('#resultat').append('<li class="liste" ><iframe id="ytplayer" type="text/html" width="140" height="100" src="http://www.youtube.com/embed/RD98kNOBrNs?hd=1&rel=0&autohide=1&showinfo=0&wmode=opaque" frameborder="0"/></li>').listview("refresh");
I'm using z-index and position attributes to place my div manually above the iframe, but I don't think it's a good idea to do it automatically.
Thanks
In addition to Matyas his answer, I have altered his code a bit such that it is now fully implementable.
First, take a look at the demo before I will explain all the details:
SEE DEMO CODE HERE
As you can see, I 'soft coded' all the widths and the heights such that the overlayDiv is placed exactly in the middle of the iFrame.
You can change the width and the height of the overlayDiv to whatever you want and the script will automatically adjust the position of the start button.
What is very important is that you must have the following order in your HTML for this to work:
<div id="vidFrame" class="play">
<iframe id="video" class="youtube-player" type="text/html" width="520" height="330" src="http://www.youtube.com/embed/-PZLM-CmuJ0?wmode=opaque&hd=1&rel=0&autohide=1&showinfo=0&enablejsapi=1" frameborder="0"></iframe>
</div>
<div class="overlayDiv">
<img src="https://www.ameliaconcours.org/UploadedContent/Lamborghini%20Logo_Crest_4C_S.png" alt="facebook" width="90px" />
</div>
Where the width and height of vidFrame doesn't have to be established beforehand because it will become the height of the iFrame.
Also, mind the following details:
wmode=opaque is the first argument we give to the video (must be the absolute first)
we enable the enablejsapi=1 such that we gain control over playing (and pausing) the video
The jQuery that I use is the following:
$.fn.loadOverlay = function() {
$('iframe').each(function(idx, iframe){
var imageHeight = $('.overlayDiv').height();
var imageWidth = $('.overlayDiv').width();
var marginTop = $('#video').height();
var marginTop = marginTop/2-imageHeight/2;
var marginLeft = $('#video').width();
var marginLeft = marginLeft/2-imageWidth/2;
$('.overlayDiv')
.clone()
.appendTo('body')
.css({
top: marginTop,
left: marginLeft,
}).show();
});
}
Note that, eventhough it is lengthy, it explicitly calculates the middle of the iFrame. Hence, shorter methods are possible but this one will make you understand exactly what is happening.
Now another thing: yt players always have the ugly red play button in the middle of their iFrame when loading a video.
There is a little hack to make this button disappear, namely:
function onPlayerReady(event){
//THIS IS THE TRICK THAT YOU MIGH WANT TO REMOVE
player.playVideo();
player.pauseVideo();
}
So essentially we play and then immediately pause the video to make the button disappear.
But mind you: this wil not work on mobile devices. A very big advantage of this is that the video will automatically start buffering which is an advantage for the user.
Furthermore, the jsFiddle is self-explanatory so just read it through and try to understand it.
I hope this answers your question. Good luck!
$('iframe').each(function(idx, iframe){ // for each iframe
var $iframe = $(iframe); // take its jquery reference
$('.overlayDiv') // grab the overlay template you wish to place over each
.clone() // clone it
.appendTo('body') // add it to the end of your page
.css({ // resize and position the overlay
top: $iframe.offset().top, // to fit just above the iframe
left: $iframe.offset().left,
height: $iframe.height(),
width: $iframe.width(),
}).show(); // show the hidden (by CSS) overlay
});
Initially your .overlayDiv should have the following styles:
.overlayDiv {
position: absolute; /* so when we position by js it will be above the iframe*/
display: none; /* the master tempalte should be hidden */
z-index: 4953; /* make sure the overlay appears above other elements */
}
I haven't tested it out, Just written it from scratch while my build was running. But this is the idea I'd go with. You might have to tinker with the positioning.
I'm trying to fetch and print out width and height attributes from video with a simple javascript, but for some reason I'm not managing.
This is the javascript
video = document.getElementsByTagName("video")[1];
span1 = document.getElementById("dimensions");
span1.innerHTML = video.videoWidth + " x " + video.videoHeight;
and this is html5 code which it affects (this is the second video tag in html structure)
<figure>
<video controls>
<source src="video.webm" type="video/webm">
</video>
</figure>
<p>
Dimensions: <span id="dimensions"></span>
</p>
Thanks a lot, I'm a beginner so be light on me.
Your index, based on your markup, won't return you the element you want. The index is zero-based as node lists are array-like and start indexing at 0.
var video = document.getElementsByTagName("video")[0];
Edit: sorry, didn't see you said it was the second video tag. In that case, I'm not certain, because it works for me: http://jsfiddle.net/3wCYz/1/
One thing you might want to try is putting the code you use to get the width and height inside a handler on your video tag that listens for the loadedmetadata event:
video.addEventListener("loadedmetadata", dimensionFunction, false);
where dimensionFunction is a function that does what you're already doing to grab the dimensions.
What this does is make sure the metadata for the video has downloaded before you try to grab it.