Reputation: 15683
I created a very basic slideshow by repeating the jQuery
effects with setInterval
. However, there is a mismatch in timing after each cycle of the setInterval
. After a few cycles, it leads to a visible mismatch in two parallel slide effects.
The code is
$(document).ready(function(){
var frontslides =$("#first li").length,
slideTime=500,
slideCycle=parseInt(slideTime*frontslides);
function frontSlide(){
$("#first li").each(function(n){
$(this).delay(slideTime*n).fadeIn(400).fadeOut(100);
$("#second li").eq(n).delay(slideTime*n).fadeIn(400).fadeOut(100);
});}
frontSlide();setInterval(frontSlide, slideCycle);});
The working example is here
To save your valuable time, its speed is fast, but it happens on any speed. After a few cycles, you can see that left and right slides are no longer synchronized.
Upvotes: 0
Views: 1184
Reputation: 49238
Since I opened my mouth, here is the version I came up with. I added a blocked
flag in there to indicate an effects loop was currently running, hopefully preventing the script from overrunning itself. I also added a factor
value so that if overrunning did occur, it would loop more quickly, to preserve the appearance that the loop was not disrupted.
If you have any other questions about it, just let me know. It's pretty straight forward.
$(document).ready(function() {
var $sel = $('#left, #right').find('li:first-child'),
slidetime = 200,
timein = 400,
timeout = 100,
blocked = false;
var fadeout = function() {
$sel.fadeOut(timeout, next);
};
var next = function() {
if ($sel.is(':last-child')) {
$sel = $sel.siblings(':first-child');
} else {
$sel = $sel.next();
}
blocked = false;
};
(function slider() {
var factor = .2;
if (!blocked) {
factor = 1;
blocked = true;
$sel.fadeIn(timein, fadeout);
}
setTimeout(slider, slidetime * factor);
})();
});
Upvotes: 1
Reputation: 20179
You could move the transitioning to the next slide in a separate function and call it with setTimeout
. Then, you just store the slide number in a variable and increment it after each function call.
$(document).ready(function(){
var firstSlides = $("#first li"),
secondSlides = $("#second li"),
nbSlides = firstSlides.length,
slideTime = 500,
nextSlide = 0;
function slideshow() {
firstSlides.eq(nextSlide).fadeIn(400).fadeOut(100);
secondSlides.eq(nextSlide).fadeIn(400).fadeOut(100);
nextSlide = (nextSlide+1) % nbSlides;
setTimeout(slideshow, slideTime);
}
slideshow();
});
Here's a fiddle of this first approach.
If you want to absolutely guarantee that both animations are completed when starting the next animation, you can use the new promises from jQuery 1.6. You can call $.promise()
on both jQuery objects to get a promise which will be resolved when all animations of that element are completed. Then, you can set up a master promise with $.when(promises...)
which will be resolved when all the given promises are resolved and set up a then
handler.
$(document).ready(function(){
var firstSlides = $("#first li"),
secondSlides = $("#second li"),
nbSlides = firstSlides.length,
fadeInTime = 400,
fadeOutTime = 100,
nextSlide = 0;
function slideIn() {
var p1 = firstSlides.eq(nextSlide).fadeIn(400).promise();
var p2 = secondSlides.eq(nextSlide).fadeIn(400).promise();
$.when(p1, p2).then(slideOut);
}
function slideOut() {
var p1 = firstSlides.eq(nextSlide).fadeOut(100).promise();
var p2 = secondSlides.eq(nextSlide).fadeOut(100).promise();
nextSlide = (nextSlide+1) % nbSlides;
$.when(p1, p2).then(slideIn);
}
slideIn();
});
For a simple slideshow, you probably won't notice much of a difference. However, with promises you can make much more advanced transition sequences with funky timings while still maintaining synchronisation.
Here's a fiddle of that approach.
Upvotes: 4
Reputation: 5679
Set the animations to both run at the "same" time:
function frontSlide(){
$("#first li").each(function(n){
var _ = $(this);
setTimeout(function() {
_.fadeIn(400).fadeOut(100);
$("#second li").eq(n).fadeIn(400).fadeOut(100);
}, slideTime*n);
});
}
Upvotes: 2