Michael Caley
Michael Caley

Reputation: 46

Animate sequence going haywire

I have a sequence of images fading out and then back in which appears to work well for about 2 loops. Unfortunately after that it goes crazy and the sequences appears to go completely random.

I have done a fiddle so you can see what's going on https://jsfiddle.net/MichaelCaley/Lmm3kp4m/

var imgshow = function(){
    $(".img1").delay(2000).animate({
        opacity: 0
    }, 3000, function(){
        $(".img2").delay(2000).animate({
            opacity: 0
        }, 3000, function(){
            $(".img3").delay(2000).animate({
                opacity: 0
            }, 3000, function(){
                $(".img1").delay(2000).animate({
                    opacity: 1
                }, 3000, function(){
                    $(".img2, .img3").animate({
                        "opacity": "1"
                    }, 0, function(){
                        imgshow();
                    });
                });
            });
        });
    });
}

imgshow();

After the first run through I've done a sort of reset step which is supposed to be the only time 2 classes are changing at the same time, but when I watch the loop go through I start to see that multiple divs begin fading throughout the process which I just cannot understand.

Thank you for your help

Upvotes: 1

Views: 35

Answers (1)

GMchris
GMchris

Reputation: 5648

It's very easy to get confused or lost in callback hell, especially with jQuery animations and especially especially when using delay. May I suggest something a bit more clean, in my opinion at least.

// Get all images that need to be looped.
var images = $('.some-class-all-images-share');
// Create an array to store images that have already been shown.
var cycled = $([]);
// Start an interval, which calls the same function every 5 seconds.
setInterval(function(){
  // Get the first image from the images array.
  var image = images.unshift();

  // If the images array is empty, reset everything.
  if (images.length === 0) {
    images = cycled;
    cycled = $([]);
    images.removeClass('transparent');
  }
  // Add a the class 'transparent' to the image.
  image.addClass('transparent');
  // Add the image to the cycled images array.
  cycled.add(image);
}, 5000);

In the CSS:

.some-class-all-images-share {
  /* This means that whenever the opacity of the element changes, it will do so gradually, over three seconds, instead of instantly.*/
  transition: opacity 3s;
}

.transparent {
  opacity: 0;
}

Now every image will get the transparent class applied to it, one by one. This will trigger a three second long animation, and when all images except for the last one have been animated, it will restart. This way you don't need another callback for each image and it should be, overall much more manageable.

Upvotes: 1

Related Questions