I need to change images in a slide of an image slider.
Every slide contains two images which will change after 3 seconds.
So, the slide comes with the first image, after 3 seconds it changes the first image to the second image and after another 3 seconds ( so 6 seconds total ) the current slide goes and the next slide comes.
My idea is to use setTimeOut
function and to call every 3 seconds another image.
So after 3 seconds fadeOut()
the first image and fadeIn()
the second.
I tried this using cycle2 and its cycle-after
and cycle-before
event:
$('.slide .center img:nth-child(2)').hide(); // hide all slides second images
$('#slides').cycle({
fx: 'scrollHorz',
slides: '>.slide',
timeout: 6000,
prev: '#prev',
next: '#next'
});
$('#slides').on('cycle-before', function(event, optionHash){
setTimeout(function(){
$('.slide:eq('+optionHash.currSlide+') > .center > img:first-child').fadeOut(1000);
console.log($('.slide:eq('+(optionHash.currSlide)+')').attr('slideNum'));
},1000)
setTimeout(function(){
$('.slide:eq('+optionHash.currSlide+') > .center > img:nth-child(2)').fadeIn();
console.log($('.slide:eq('+(optionHash.currSlide)+')').attr('slideNum'));
},2000)
});
$('#slides').on('cycle-after', function(event, optionHash, outgoingSlideEl, incomingSlideEl, forwardFlag) {
$('.center img:first-child',outgoingSlideEl).show();
$('.center img:nth-child(2)',outgoingSlideEl).hide();
});
But this doesn't work as I expected. It doesn't change the images and it breaks on next
and prev
button. If you see the console, you'll see that it doesn't trigger the current slide
.
Any help is appreciated.
If you inspect the HTML code generated by JavaScript, you'll notice that Cycle2 duplicates the first slide and makes it invisible. The reason for this is beyond me, but at least we can easily work around it.
Secondly, you should trigger the fade-in/fade-out animation in cycle-after
. If this is done in cycle-before
, the setTimeout
counter begins while the slideshow is still transitioning to the next slide. Another problem is that in cycle-after
, optionHash.currSlide
is set to the previous slide...
In order to work around all those issues, we have to calculate the index of the currently visible slide like so:
var visibleSlide = ((optionHash.currSlide + 1) % optionHash.slideCount) + 1;
Regarding the broken previous/back buttons, it actually should be enough to completely stop the fade-in/fade-out animation and reset it when one of the buttons is clicked. However, when the prev button is clicked, the index calculation has to be adjusted (-1
instead of +1
, see code below).
Furthermore, we have to trigger the fade-in/fade-out animation "manually" for the very first slide right after initialization of the slideshow. To do this, we can use the cycle-initialized
event combined with the logic from cycle-after
.
I guess code says more than a thousand words, so here is my suggestion:
$(".slide img:nth-child(2)").hide();
// Workaround for first slide right after initialization
// Handler has to be set before initialization, otherwise it might never be called!
$("#slides").on("cycle-initialized", function(event, optionHash){
// Pretend the slideshow just transitioned from the last slide to the first
onCycleAfter(optionHash.slideCount-1, optionHash.slideCount);
});
$("#slides").cycle({
fx: "scrollHorz",
slides: ".slide",
timeout: 6000,
prev: "#prev",
next: "#next"
});
var timeout, prevClicked = false;
$("#slides").on("cycle-after", function(event, optionHash){
onCycleAfter(optionHash.currSlide, optionHash.slideCount);
});
$("#slides").on("cycle-prev", function(){
prevClicked = true;
});
function onCycleAfter(currSlide, slideCount) {
// Reset slides
$(".slide img:first-child").show();
$(".slide img:nth-child(2)").hide();
// Reset animation
clearTimeout(timeout);
$(".slide img").finish();
// Calculate current slide (with workaround for prev button)
var visibleSlide;
if (prevClicked) {
visibleSlide = ((currSlide - 1 + slideCount) % slideCount) + 1;
prevClicked = false;
}
else {
visibleSlide = ((currSlide + 1) % slideCount) + 1;
}
// Trigger new animation
timeout = setTimeout(function(){
var slideImages = $(".slide").eq(visibleSlide).find("img");
slideImages.eq(0).fadeOut(1000, function(){
slideImages.eq(1).fadeIn(1000);
});
}, 1000);
}