I'm looking to create a video parallax background, but I want that the progress of the video corresponds to where I am on my webpage.
For example :
When im on the top of the page the video is at 0 seconds,
in the middle at 50% of its total runtime
and finishes only when I reach the bottom of the page.
You have to break down the big problem into smaller problems.
First, you need to get your video's duration :
var vid = document.getElementById("myVideo");
duration = vid.duration;
Next, you need to get the scroll amount in percentage
function getVerticalScrollPercentage (elm) {
var p = elm.parentNode
return (elm.scrollTop || p.scrollTop) / (p.scrollHeight - p.clientHeight ) * 100
}
Next, you need to dynamically set your video's currentTime (in seconds), you can do it this way :
vid.currentTime = duration * percentage / 100;
And finally, you need to set the currentTime again, whenever the scroll amount changes. That is achieved by using an event listener, on the body for example.
object.addEventListener("scroll", myScript);
Now put it all together :)
Related
I have developed an audio slider (the slider down the bottom which allows you to scrub through the track) similar to SoundCloud's, and it all works perfectly, except for one thing; it flickers back and forth between the width [/ time] of the previous playing track, and the current playing track.
I have no idea as to why this is happening and have been stumped on it for quite a while.
This is my current block of JavaScript & jQuery:
function trackToSlider(wave){
// get the duration of current playing song
var waveDuration = wave.getDuration();
// check every 0.1s how far in the song is
var getWidthAndMax = setInterval(function(){
// currentWidth is the current percentage of the width of the slider from 100%
var currentWidth = (wave.getCurrentTime() / waveDuration) * 100;
makeSliderIncrease(currentWidth, waveDuration);
}, 100);
function makeSliderIncrease(currentWidth, maxWidth){
// if the current time is more than or equal to the songs duration, set the width of the slider to 100% and clear the interval
if(currentWidth >= maxWidth){
clearInterval(getWidthAndMax);
$('#inner-slider').css('width', '100%');
// otherwise set the width percentage equal to currentwidth
} else {
$('#inner-slider').css('width', currentWidth + '%');
}
}
}
Here are the relative elements inside my HTML:
<!-- play or pause track button !-->
<div onclick="trackToSlider(wave);"></div>
<!-- the audio slider which keeps on flickering !-->
<div class="audio-slider-container">
<div id="outer-slider">
<div id="inner-slider"></div>
</div>
</div>
I hope you all sort of understand where I am at currently. I have attempted to comment everything to make it easier to understand.
I feel like the problem is that because it's set a width already, before it moves onto the next track, when the new track attempts to set the new width, it's flicking between the two widths consistently, but I could be wrong.
All help or suggestions are appreciated,
Thanks. :-)
I think it's beacouse you use the same div for every track. My assumption is that your clearInterval function resets currentWidth of wave, and makes it go back to 0 invoking tracktoSlider twice. But that's all I can say based on given code. Try to add a #inner-slider to html each time you start a new track, and remove it each time when track ends
I am working with js greensock animation library. I have an animation that pauses when you start to resize the window and continues when you stop resizing the window.
I am now attempting to make the animation (Start over) or from a (certain point) if the window width passes 865px in either direction.
The current code im working with works "Okay" it refreshes the entire page upon reaching 865px in either direction. However, instead of reloading entire page I would just simply like to "restart" the animation.
Here is a working CODEPEN
And here is the snippet of JS that I am working with and referring to.
//Reload Animation if window width crosses over 865px either way.
var ww = $(window).width();
var limit = 865;
function refresh() {
ww = $(window).width();
var w = ww<limit ? (location.reload(true)) : ( ww>limit ? (location.reload(true)) : ww=limit );
}
var tOut;
$(window).resize(function() {
var resW = $(window).width();
clearTimeout(tOut);
if ( (ww>limit && resW<limit) || (ww<limit && resW>limit) ) {
tOut = setTimeout(refresh, 0);
}
});
Thanks!
There is no need to refresh the whole page. There are several ways to manipulate a Tween or Timeline.
If you want to play it from the beginning the easiest way would be:
myTimeline.restart()
Alternatively you could change the progress and play the animation from that point:
myTimeline.progress( myProgress )
The placeholder myProgress can be 0 marking the start and 1 being the end of the Tween (or any number inbetween). So the code to play it from the start would look something like this:
myTimeline.progress( 0 ).play()
A third way would be .play( time )
This is similar to .progress() with the difference that myProgress is a relative measurement and time is an absolute one. So if the duration of myTimeline is 8 seconds myTimeline.progress(0.5).play() would have the same result as myTimeline.play(4)
EDIT:
Here is a fork of your Pen. I believe it does what you are looking for:
http://codepen.io/anon/pen/adqypP
You can call .restart() which restarts and begins playing forward from the beginning when using TweenMax or TweenLite.
API infos here:
https://greensock.com/docs/TweenMax/restart()
I was wondering how I could control/edit the status bar of an html5 video controller (i think that's what its called.. Its the bar that has your current position in the video)?
What I'm trying to do is create a program that will enable a user to pick part of the video and loop it over and over again.
Once a user hits a button, there will be 2 slider buttons underneath the progress bar, (one for beginning and ending) and the user can select the beginning and ending times by sliding the sliders and having the program highlight the portion they selected.
What I am confused about is how the video element (progress bar) is effected by the java script, and how to make the selection portion of the bar. (the highlighted section)
any help would be awesome.
here are pictures of what I am trying to explain
http://imgur.com/a/XX1e3#0
Thanks Guys
The progress bar of a <video> element isn't really "affected" by JS, per se...
The progress bar is little more than a <div> with coloured <div>s inside (to show progress).
The video object (the JS object) has properties and methods which control playback/position, and fire update events to allow you to react.
<video id="my-video" src="/media/my-video.mp4"></video>
Then the JS properties of that object are pretty straightforward:
var video = document.querySelector("#my-video");
video.play(); // plays
video.pause(); // pauses
video.currentTime; // gets or sets the current playback time
video.duration; // gets the length of the media file
// stop doesn't exist, but it's easy enough to make
video.stop = function () { video.pause(); video.currentTime = 0; };
video.addEventListener("timeupdate", function () {
/* more of the video has played */
});
All you really need to do here, is spend some time thinking about how the bar itself will operate.
If 100% of the bar is equal to 100% of the video's duration, then as users click on other divs to move them around, you can figure out where those cursors are on the time-bar...
eg: your bar is 500px, your video is 300 seconds.
The user sets one cursor to 100px from the left of the bar (100px/500px == 0.2 * 300s == 60s).
So now you know that when you loop back around, you're going to set video.currentTime = 60;.
How do you know when to do that?
video.addEventListener("timeupdate", function () {
var end_percent = end_cursor_pos_px / bar_width_px,
start_percent = start_cursor_pos_px / bar_width_px,
end_time = video.duration * end_percent;
if (video.currentTime > end_time) {
/* set video.currentTime to the "start_time" */
video.currentTime = video.duration * start_percent;
}
});
As a performance consideration, you should update the start-percent/end-percent whenever the user moves either cursor.
Then, when the video tells you it's played more, you should calculate the percentage of the duration.
Note that you might not have the full duration available to you until the video has played a bit (or until it's played all the way through, even).
There is a "loadedmetadata" event you can listen to, that will tell you when you've got it all.
But still, if only 30 seconds have loaded, 50% of 30 seconds is still 50%.
If you want that not to be the way it works, then you need to work around it, either by waiting for that event (even if the video has to be 100% done), or by sending it in a JSON request, or reading it from headers in an AJAX "HEAD" request.
The math for the positions of the cursors and bar is pretty easy, too.
As long as you guarantee that the cursors stay within the bounds of the bar, (and the user hasn't scrolled the window to the point where part of the bar is off-screen, left or right), it's just going to be:
var start_cursor = startEl.getBoundingClientRect(),
end_cursor = endEl.getBoundingClientRect(),
scrub_bar = scrubEl.getBoundingClientRect();
var start_percent = (start_cursor.left - scrub_bar.left) / scrub_bar.width,
end_percent = (end_cursor.left - scrub_bar.left) / scrub_bar.width;
If they have scrolled left/right, then you just want to add window.pageXOffset to those values.
There isn't much more to it.
Just be sure to update the start/end percent any time a cursor gets moved, and check your playback percentage against the end-percent, and update the currentTime, any time it's gone past (the callbacks happen several times a second).
Hope that helps a little.
I'm trying to fade in-out my image for my photo gallery switching. All it's done in JavaScript which simply changes the opacity CSS value of the image element. This is really laggy (slow) on some computers - for example my laptop which isn't extremely powerful, but it's brand new (Asus Eeepc).
I was wondering if there's anyway I can fix this performance issue. I've seen demos of Canvas animation and HTML5 applied to images and they're really smooth on my laptop. I wonder if I can apply the same thing to my image fading feature.
Any ideas? How would I do this?
I quickly threw together an example of an image fading away using the canvas tag as requested: http://jsfiddle.net/6wmrd/12/ (Only tested in Chrome and Firefox)
I´m not sure if there is any performance gain though, but here is at least a very simple example of how it can be done. It should also be noted that this was done in 5 min so the code can be improved and optimized.
Otherwise, from my experience, if you have a solid background behind the image, I have found that it is sometimes smoother to fade an element over the image with the same color as the background.
Other ways you can improve performance could be to reduce FPS. If I´m not mistaken MooTools has 50 FPS as standard. However, reducing the FPS might influence the perceived performance.
Here is code that works for all browsers:
add to head :
/* ****************************
* updated for all browsers by
* Evan Neumann of Orbiting Eden on
* October 6, 2011.
* www.orbitingeden.com - evan#orbitingeden.com
* original version only worked for IE
*****************************/
<!-- Begin
/* *****************************
* * editable by user
* ***************************/
var slideShowSpeed = 5000; // Set slideShowSpeed (milliseconds) shared by IE and other borwsers
var crossFadeDuration = 5; // Duration of crossfade (1/10 second) shared by IE and other borwsers
var crossFadeIncrement = .05; //crossfade step amount (1 is opaque) for non-IE browsers
// Specify the image files
var Pic = new Array(); // do not change this line
// to add more images, just continue the pattern, adding to the array below
Pic[0] = 'images/dare2wear-427ED-e.jpg';
Pic[1] = 'images/PBW_3238EDSM-e.jpg';
Pic[2] = 'images/dare2wear-441_2ED-e.jpg';
/* ********************************
* do not change anything below this line
**********************************/
var f = 0; //index of the foreground picture
var b = 1; //index of the background picture
var p = Pic.length; //number of pictures loaded and in queue - this may increase as time goes on depending on number and size of pictures and network speed
//load the picture url's into an image object array
//used to control download of images and for IE shortcut
var preLoad = new Array();
for (i = 0; i < p; i++) {
preLoad[i] = new Image();
preLoad[i].src = Pic[i];
}
function runSlideShow() {//this is trigerred by <body onload="runSlideShow()" >
//if IE, use alternate method
if (document.all) {
document.images.SlideShow.style.filter="blendTrans(duration=2)";
document.images.SlideShow.style.filter="blendTrans(duration=crossFadeDuration)";
document.images.SlideShow.filters.blendTrans.Apply();
}
//increment the foreground image source
document.images.SlideShow.src = preLoad[f].src;
//if IE, use the shortcut
if(document.all) {
document.images.SlideShow.filters.blendTrans.Play();
}
//all other browser use opacity cycling
else {
var imageContainer = document.getElementById('imageContainer');
var image = document.images.SlideShow;
//convert an integer to a textual number for stylesheets
imageContainer.style.background = "url('"+Pic[b]+"')";
//set opacity to fully opaque (not transparent)
image.style.opacity = 1;
//run fade out function to expose background image
fadeOut();
}
//increment picture index
f++;
//if you have reached the last picture, start agin at 0
if (f > (p - 1)) f = 0;
//set the background image index (b) to one advanced from foreground image
b = f+1;
//if b is greater than the number of pictures, reset to zero
if(b >= p) {b = 0;}
//recursively call this function again ad infinitum
setTimeout('runSlideShow()', slideShowSpeed);
}
function fadeOut(){
//convert to element
var el = document.images.SlideShow;
//decrement opacity by 1/20th or 5%
el.style.opacity = el.style.opacity - crossFadeIncrement;
//if we have gone below 5%, escape out to the next picture
if(el.style.opacity <= crossFadeIncrement) {
return;
}
//wait 50 milliseconds then continue on to decrement another 5%
setTimeout('fadeOut()', crossFadeDuration*10);
}
// End -->
and add two elements to the body. The first is a container background element. I have used a div, but td, body and others should work too. The second is the foreground image. Lastly, within the <body> tag, add the onload function call
<body onLoad="runSlideShow()">
<!-- this is the main image background -->
<div id="imageContainer">
<!-- this is the main image foreground -->
<img id="SlideShow" name='SlideShow' width="324" height="486">
</div>
Luca one way to make it faster is to use hardware acceleration and webkit transforms. The problem is that different browser support this to different degrees. See
http://mir.aculo.us/2010/06/04/making-an-ipad-html5-app-making-it-really-fast/
hopefully in the not-to-distant futures support for hardware acceleration in the browser will be better.
Have a look at the front page of this site It's 5 images that fade in and out in rotation, pure css2, html4, javascript, and is cross-browser (as far as I am aware). The javascript is a bit hackneyed - written some time ago :) but it seems to be smooth enough. See how it is on your machine. If it lags, you could try with a slower update, say 150 or 200ms instead of a 100.
For a while now i have been trying to figure out the algorithms behind smooth slides, fades etc..in javascript. Just to give you an example of what am talking about, I have seen a div with content in it that had a height of 0px and on toggled, it didn't just snap to height, it smoothly and gradually grew to height using some sort of function. What i do know is that the height of this div was being assigned its height value from either a date object that had an interval set or a loop of some sort. I've searched all over the web trying to find tutorials explaining how this works but failed. Can someone please either explain to me how to create my own smooth fades, slides or reference some links that i can read?
PS: I know i can just use jquery, but i want to know how the fades and slides actually work.
It's quite simple actually. All of these animations use a timer (see setInterval) with a short interval, say 100 milliseconds, and every time the timer fires, the property (height or whatever) is changed by a fraction of the total amount instead of all at once.
For example, if you want to slide from a height of 0px to 200px in 1 second, then you could set up a timer that fires every 100 ms and increases the height of the DIV by 20px. That way, in 1 second, the timer would have fired 10 times and the height would be 200px.
A simple example:
function slideOpen(elem, finalHeight, slideTime) {
var count = slideTime * 10; // 10 intervals per second
height = 0, // current height
delta = finalHeight / count; // change in height per interval
var timerId = setInterval(slide, 100);
function slide() {
height += delta;
elem.style.height = height + 'px';
if (--count == 0)
clearInterval(timerId);
}
}
I have never looked at the jQuery code myself, but i'm pretty sure it uses a loop/timeout to increment the top/left/bottom/right css position of the element gradually using the specified easing equation.
You might want to have a look at jQuery source code for the animate() function.
CSS3 makes it trivial.
For non-CSS3 based solution, this is the first Google result for the query "javascript smooth animation": http://www.schillmania.com/content/projects/javascript-animation-2/
I am adding some code from one of my projects to move the div right
belolw xs_tuck() will be called till finalleftpositionval reaches
This code makes the div move to right.
if(xs_endpt<finalLeftPositionVal){
xs_endpt+=5;
xs_pDiv2.style.left=xs_endpt;
setTimeout("xs_tuck();",20);
}