I am a JS novice so go easy on me here. But I wrote a simple slideshow and it seems to be running very slow. The code below takes about 2-4 seconds to load locally on my own machine. Wondering what is causing the delay. Let me know, thanks!
function slideshow(){
$("#1").animate({top: "50px",}, 500).delay(2000);
$("#1").animate({top: "400px",}, 500);
$("#2").animate({top: "50px",}, 500).delay(2000);
$("#2").animate({top: "400px",}, 500);
$("#3").animate({top: "50px",}, 500).delay(2000);
$("#3").animate({top: "400px",}, 500);
$("#4").animate({top: "50px",}, 500).delay(2000);
$("#4").animate({top: "400px",}, 500);
$("#5").animate({top: "50px",}, 500).delay(2000);
$("#5").animate({top: "400px",}, 500);
slideshow();
}
Each ID represents a different image.
The big problem with your code, since none of the other answers seem to have talked about it yet, is that the last line of slideshow() calls itself recursively, which will lead to a stack overflow. Don't do this:
function slideshow() {
// animate code
slideshow();
}
Instead, if you want it to run repeatedly, use setTimeout() to queue another execution of the function x milliseconds later:
function slideshow() {
// animate code
setTimeout(slideshow, 3500);
}
The way you had it, none of the functions ever actually finishes. With setTimeout(), each invocation of slideshow() does finish, and then a separate one runs after the specified delay. I'd make the delay big enough that the next invocation occurs after the current animations finish, otherwise you'll be queuing up more and more animations faster than they run.
UPDATE: jQuery maintains separate animation queues for each element, which means that the animations on your five elements will run simultaneously. Some of the other answers already provide ways of running the animations in sequence one at a time, but here is how I'd do it:
$(window).on("load",function() {
// cache a jQuery object containing the elements to animate
// (note you don't need their ids if you use their class)
var $imgs = $('img.slideshow-image'),
i = 0;
function slideShow() {
// start animation for "current" img
$imgs.eq(i).show(1)
.animate({top: "50px",}, 500)
.delay(2000)
.animate({top: "400px",}, 500)
.hide(1, function() {
i = (i+1) % $imgs.length;
setTimeout(slideShow, 500);
});
}
slideShow();
});
Working demo: http://jsfiddle.net/bARwb/
I've wrapped the code in a load handler both to remove the need for an inline onload= attribute and as a convenient way of keeping the code out of the global scope (if you do it this way don't forget to remove onload="slideShow()" from your body tag).
I've added .show() and .hide() calls (with a duration so that they join the animation queue) so that the img elements will have display:none in between animations because otherwise with your position:relative style you can't see any but the first (but changing to position:absolute would prevent them getting cropped by their parent's overflow:hidden).
When the animation finishes for an element, the callback from .hide() increments i to refer to the next element's index (but checks for when it goes past the last element) and then uses setTimeout() to queue the animation for that next element.
You have some duplication in there, and also some incorrect assumptions.
When you call .animate in jQuery, you can specify a callback that will be called when the animation is complete. This is the place to put your "next step".
So in this example:
animate the image
when complete, wait 2 seconds
after 2 seconds, animate the image
when complete, call the function with the next image
This is how it looks
var images = ['#1', '#2', '#3', '#4', '#5'];
function slideshow(index){
if (index >= images.length) {
index = 0;
}
var image = images[index];
$(image).animate({top: "50px",}, 500, function () {
window.setTimeout(function () {
$(image).animate({top: "400px",}, 500, function () {
slideshow(index + 1);
});
}, 2000);
});
}
my guess is that you are setting your frames to 2 seconds (2000). Try something speedier like 50 and see what you see. I'm not sure if that's the frame delay or the 500 but if either of those represents how long you are waiting between frame changes it's way too long.
Other than the intentional delays in your code, i do not see anything that would cause the slow loading. It may be the rest of the page. I would check to see how large your images are and any other files that may be downloading before the JavaScript slideshow function executes.
As a side note, it is strange that you call slideshow from within the slideshow function.
You could try something like this:
var intervalValue = setInterval( "slideshow()", 2000 );
var slideshow_imageindex = 1;
function slideshow()
{
//check if imageindex is greater than the number of images available (5 is an example)
if (slideshow_imageindex > 5)
{
slideshow_imageindex = 1;
}
//hide image below, change image src, then move image so that it is visible again
$("#1").animate({top: "400px",}, 500).attr('src','img/Slideshow-Audio-Trsfr'+slideshow_imageindex+'.png').animate({top: "50px",}, 500);
//increase image index
slideshow_imageindex++;
}
You will only need a single img (i kept your "id=#1" img), and every 2 seconds the image is hidden, it changes and the it is shown again. Only things you have to do: name the images so that only the number changes, like:
img/Slideshow-Audio-Trsfr1.png
img/Slideshow-Audio-Trsfr2.png
img/Slideshow-Audio-Trsfr3.png
img/Slideshow-Audio-Trsfr4.png
img/Slideshow-Audio-Trsfr5.png
and then use the number of images in the "if" within the function. It's late here in italy, hope i didn't forget anything :)
Related
I have a little jQuery function in my Asp.Net MasterPage that fades an image out after 3 seconds. It works fine, but I'm having difficulty getting it to fade back in. I've tried several things as I'm new using jQuery, and I know there's something I'm doing or not doing. I can't put my finger on it. Here's what I have:
<script src="/Scripts/jquery-2.1.1.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function (){
setTimeout(function (){
$('#Image1').fadeOut('slow', function(){
$('#Image1').remove();
});
}, 3000);
});
var fadeBack = function () {
$('#Image1').fadeIn();
};
fadeBack();
</script>
Like I said, it fades out with no problem, but I cannot find the right code structure to bring it back in. I'm thinking maybe an If statement block about the opacity is needed?
The real trick is that I want alternate images in 3 boxes I have as seen here:
I have about 12 images total, and just want them to fade one image out, and bring another in. Being more specific, I mean the following:
Column (1): Image1.FadeOut(); Image2.FadeIn(); Image2.FadeOut(); Image3.FadeIn(), and etc.
So for now, I just need help with how to do this in Column One, and I'll see if can string something together to make the other Columns 2 and 3 follow up. The timing would be 3 second for each.
Lastly, could I use an array to store other images which aren't in the Column One box already and call them into the slideshow fade sequence? I appreciate you help for this knowledge, so I can lock this in mind. Thanks.
Use this code, it will hide the image after 3 seconds and after that 1 sec, it will show image back.
$(document).ready(function (){
setTimeout(function (){
$('#Image1').fadeOut('slow');
}, 3000);
setTimeout(function (){
$('#Image1').fadeIn('slow');
}, 4000);
});
if you want like a slideshow use this code
<div class="yourimg_container">
<img src="http://localhost/app/img/off.png" id="Image1"/>
</div>
/* make an array containing your images path (you can fetch images from database using asp.net/php query)*/
var ss= ["http://localhost/app/img/off.png",
"http://localhost/app/img/on.png",
"http://localhost/app/img/slider.png"];
window.setInterval(function(){
slideshow();
}, 3000);
function slideshow(){
var im=$("#Image1").attr("src");
for(i=0;i<ss.length;i++){
if(ss[i]==im){
if(i==ss.length-1) $('#Image1').attr("src",ss[0]);
else $('#Image1').attr("src",ss[i+1]);
}
}
}
additionally you can use other effects like this
function slideshow(){
var im=$("#Image1").attr("src");
for(i=0;i<ss.length;i++){
if(ss[i]==im){
if(i==ss.length-1) {
$('#Image1').fadeOut(500);
$('#Image1').attr("src",ss[0]);
$('#Image1').fadeIn(700);
}
else {
$('#Image1').fadeOut(500);
$('#Image1').attr("src",ss[i+1]);
$('#Image1').fadeIn(700);
}
}
}
}
Your fadeBack() is launched immediately whereas the fadeOut has 3 sec delay. Set a timer for your fadeBack grater than 3 sec and the img will appear.
There is a function $('#Image1').remove(); Applied. It mean once fade over, the html block will be removed. Then you can't access the object. Because fade in and fade out accessing same id #Image1. So comment the line. It may work.
i'm starting to learn jquery and i am now working on an header image crossover with jquery. ive got the code working but what i now need is an interval between images, after the crossover i want the script to pause for a specific time and then continue with the next image.
ive got this code.
$(document).ready(function(e) {
$('.img:gt(0)').hide();
setInterval(function(){
$(".img:first-child").fadeOut(3000).next(".img").fadeIn(3000).end().appendTo("#kop")
}, 4000);
});
is it possible in this form or do i have to change the code completly.
i now got it running on a test server of mine. swinging.icwebdesign.nl
Currently what is happening is you're taking 3000ms to do your transition, and inbetween the transition function call is 4000ms - therefore, you'll only get a 1000ms "delay".
The second parameter in setInterval() is the delay time, which in the code below is equal to the fadeTime + delay time.
$(document).ready(function(e) {
var delay = 3000,
fadeTime = 3000;
$('.img:gt(0)').hide();
setInterval(function(){
$(".img:first-child").fadeOut(fadeTime).next(".img").fadeIn(fadeTime).end().appendTo("#kop")
}, delay+fadeTime);
});
I have made a carousel and using JavaScript setInterval() function for rotate image with fixed interval in carousel. Here's the script that I had used:
var timeOut = 4000;
function showSlide() {
//....script for showing image
}
function pauseSlide() {
setInterval(function(){showSlide();}, timeOut);
}
jQuery(document).ready(function() {
pauseSlide();
});
Now the problem is when I have change the browser tab and after few minute back again to carousel browser and what I seen carousel running too faster rather than default time interval, images going to change fast suppose 0 time interval. Please help me with how I can sort this out.
You must get rid of the first interval before starting another, or you start getting more than one interval working simultaneously (i.e. why you start seeing it go "faster")
Do this
var timeOut = 4000;
var interval = 0;
function showSlide() {
//....script for showing image
}
function pauseSlide() {
clearInterval(interval);
interval = setInterval(function(){showSlide();}, timeOut);
}
jQuery(document).ready(function() {
//NOW you can do multiple pauseSlide() calls
pauseSlide();
pauseSlide();
pauseSlide();
pauseSlide();
pauseSlide();
});
From what I know in newer versions of both firefox and chrome, background tabs have setTimeout and setInterval clamped to 1000ms to improve performance. So I think that your issue might relate to that.
Maybe this will help : How can I make setInterval also work when a tab is inactive in Chrome?
Image changing faster than expected may indicate that you have more than one call to pauseSlide(), in one way or another.
Is document ready the only place you call the function ? Any code in showslide or anywhere triggering a document ready event ? If you put an alert() in pauseSlide(), does it popup more than once ?
What I'd like to do is iterate through a navigation's list items, and fade each element in, sequentially, but with the flexibility of having two delay options: the option to wait for each previous animation to complete before proceeding with the next animation, and/or a custom delay/timeout (milliseconds) between the start of each animation (not a delay between the end of one animation and the start of the next animation).
Naturally, I could use nested callbacks and call each list item specifically, but that's rather inefficient code-wise, and would only load each element one-after-another, which is okay in some cases, but in others I might want to have them load nearly simultaneously, with a possible slight delay (to emulate some of the Flash based navigations I've seen). Hense why I say that the custom delay option should be between the start of one, and the start of the next.
For what it's worth, the navigation elements are first being hidden via $('#nav li').hide(); but I suspect you already guessed that might be the case. :)
How might this sort of effect be accomplished?
$('#nav li').each(function(index, element) {
$(element).delay(index*50).fadeIn(400); // delays each subsequent fade by 50ms.
// Change 50 to match the duration of the fade and they will fade in one after the other.
});
Check this fiddle: http://jsfiddle.net/bPbw4/7/
Suppose your nav HTML looks like:
<ul>
<li>Item-1</li>
<li>Item-2</li>
<li>Item-3</li>
</ul>
Then your JS code for the serial animation can be something like this:
var currentLi = null;
var speed = 1000;
var gap = 500;
function doNext() {
if(currentLi==null) {
currentLi = $('ul li:first');
}
else if(currentLi.next().length!=0) {
currentLi = currentLi.next();
}
setTimeout(function() {
currentLi.fadeIn(speed, doNext);
}, gap);
}
doNext();
In the above code, speed is the animation speed and gap is the delay between each fadeIn()
I suggest a simple iteration like this
(function(wait, speed) {
var itm = $('#nav li'),
len = itm.length,
index = 0;
(function sequentialFade() {
$.when( itm.eq(index).fadeIn(speed) )
.done(function() {
if (index++ === len) return false;
setTimeout(function() {
sequentialFade()
}, wait);
})
}());
}(1000, 200))
In this case I used deferred objects (jQuery 1.5+), but the idea behind this approach is to wait the end of the fadein on the nth item and then iterate the function after time milliseconds on the n+1th item.
a JsFiddle example : http://jsfiddle.net/McLZ4/3
I’m having a setTimeout problem similar to this one. But that solution doesn't help me since I can’t use php in my file.
My site has a slider with a list of images that move every 8 seconds.However, when I have opened a few tabs in the browser and then switch back again, it goes nuts.
The slider proceeds to move the images one after the other immediately without the 8 second timedelay.
I'm only seeing it in Chrome and the latest Firefox.
**EDIT: I checked with console.log() and the setTimeout returns the same number before and after the clearTimeout. Not sure why. Maybe that also has something to do with it? **
EDIT 2: I added a fiddle: http://jsfiddle.net/Rembrand/qHGAq/8/
The code looks something like:
spotlight: {
i: 0,
timeOutSpotlight: null,
init: function()
{
$('#spotlight .controls a').click(function(e) {
// do stuff here to count and move images
// Don't follow the link
e.preventDefault();
// Clear timeout
clearTimeout(spotlight.timeOutSpotlight);
// Some stuff here to calculate next item
// Call next spotlight in 8 seconds
spotlight.timeOutSpotlight = setTimeout(function () {
spotlight.animate(spotlight.i);
}, 8000);
});
// Select first item
$('#spotlight .controls a.next:first').trigger('click');
},
animate: function(i)
{
$('#spotlight .controls li:eq(' + (spotlight.i) + ') a.next').trigger('click');
}
}
From the jQuery documentation:
Because of the nature of requestAnimationFrame(), you should never
queue animations using a setInterval or setTimeout loop. In order to
preserve CPU resources, browsers that support requestAnimationFrame
will not update animations when the window/tab is not displayed. If
you continue to queue animations via setInterval or setTimeout while
animation is paused, all of the queued animations will begin playing
when the window/tab regains focus. To avoid this potential problem,
use the callback of your last animation in the loop, or append a
function to the elements .queue() to set the timeout to start the next
animation.
I finally found my answer and it’s not at all what I was expecting.
It seems the culprit is jQuery’s .animate(), which I use to move the images in the slider.
I calculate and move my images positions with this:
$('.spotlight-inner')
.animate(
{ left: scrollToVal },
{duration: 'slow'}
)
;
Now the problem seems to be that in some browsers, after you switch to a new tab and back, jQuery’s .animate() saves up the animations and fires them all at once. So I added a filter to prevent queueing. That solutions comes from CSS-Tricks.com :
$('.spotlight-inner')
.filter(':not(:animated)')
.animate(
{ left: scrollToVal },
{duration: 'slow'}
)
;
The first slide you see when you go back can act a little jumpy but it’s better than the superspeed carousel from before.
Fiddle with the full code here
There is an easier way using the jquery animate queue property:
$(this).animate({
left: '+=100'
}, {duration:500, queue:false});
I don't know if this will help you, but it helped me with my slideshow. What I did was everytime I called an animation that was supposed to happen at a set interval because of the setTimeout, I called clearQueue() which would get rid of any other animations that had been set to happen. then i'd call the animation. That way when you come back to that tab, you don't have all these animations queued up and it goes crazy. at max you'll only have one set up.
So something like this:
spotlight.timeOutSpotlight = setTimeout(function () {
spotlight.clearQueue(); // get rid of other instances of the animation
spotlight.animate(spotlight.i);
}, 8000);
It may not work in all cases (depending on timing), but I hope that helps somebody!
You must also think you use clearTimeout.
As you call setTimeout function it returns an ID you can save this ID in a variable like
timeoutID = setTimeout(function () {
spotlight.animate(spotlight.i);
}, 8000);
and before setting a new timeout you can call the function like
clearTimeout(timeoutID)
My suspicion is that the browser queues input events like 'click' but only fires them when the tab where the event occurs actually has focus.
Perhaps you should try calling your click callbacks directly instead of using trigger('click').
Something like this:
spotlight: {
i: 0,
timeOutSpotlight: null,
clickFunc: function(element) {
// do stuff here to count and move images
// Clear timeout
clearTimeout(spotlight.timeOutSpotlight);
// Some stuff here to calculate next item
// Call next spotlight in 8 seconds
spotlight.timeOutSpotlight = setTimeout(function () {
spotlight.animate(spotlight.i);
}, 8000);
},
init: function()
{
$('#spotlight .controls a').click(function (e) {
// Don't follow the link
e.preventDefault();
spotlight.clickFunc(this);
});
// Select first item
spotlight.clickFunc($('#spotlight .controls a.next:first'));
},
animate: function(i)
{
var element = $('#spotlight .controls li:eq('+spotlight.i+') a.next');
spotlight.clickFunc(element);
}
}
What version of jQuery are you running? Apparently this problem was 'fixed' for version 1.6.3 - they reverted the change that caused this to happen. Discussions here and here.
Though this issue will likely have to be addressed in the future, it seems as though we're off the hook for now.