geoff swartz
geoff swartz

Reputation: 5977

jquery animation speeds up on window resize

We have a web page with a basic jquery image slider near the top. We're running into an issue where when the browser window is minimized and then maximized again the animation speed doubles. We've confirmed this in chrome, ff and ie, however it doesn't do it every time. Some times I have to resize multiple times before it speeds up. Does anyone have any idea why it would do that? Here's the page - http://theatlasconsultingjobs.hiringhook.com/jobseeker/Search.aspx

And here's the jquery for the slider.

var fadeDuration=2000;
var slideDuration=4000;
var currentIndex=1;
var nextIndex=1;
$(document).ready(function()
{
    $('ul.slideshow li').css({opacity: 0.0});
    $("'ul.slideshow li:nth-child("+nextIndex+")'").addClass('show').animate({opacity: 1.0}, fadeDuration);
    var timer = setInterval('nextSlide()',slideDuration);
})
function nextSlide(){
        nextIndex =currentIndex+1;
        if(nextIndex > $('ul.slideshow li').length)
        {
            nextIndex =1;
        }
        $("'ul.slideshow li:nth-child("+nextIndex+")'").addClass('show').animate({opacity: 1.0}, fadeDuration);
        $("'ul.slideshow li:nth-child("+currentIndex+")'").animate({opacity: 0.0}, fadeDuration).removeClass('show');
        currentIndex = nextIndex;
}

Upvotes: 2

Views: 386

Answers (3)

Colin Bacon
Colin Bacon

Reputation: 15619

This is a problem when using animaitions and setInterval. Modern browsers will stop the animation when a tab is inactive or minimised. This will create a queue and the browser will try and execute them all once the tab is active again.

To solve this you could use clearTimeout after the animation has finished and replace setInterval with setTimeout

Example

var timer;

$("'ul.slideshow li:nth-child("+nextIndex+")'")
    .addClass('show')
    .animate({opacity: 1.0}, fadeDuration, function(){
        timer = setTimeout(function() {
                nextSlide();
            }, slideDuration);            
});

function nextSlide(){
    nextIndex =currentIndex+1;
    if(nextIndex > $('ul.slideshow li').length)
    {
        nextIndex =1;
    }
    $("'ul.slideshow li:nth-child("+nextIndex+")'")
        .addClass('show')
        .animate({opacity: 1.0}, fadeDuration);

    $("'ul.slideshow li:nth-child("+currentIndex+")'")
        .animate({opacity: 0.0}, fadeDuration)
        .removeClass('show');

    currentIndex = nextIndex;

    clearTimeout(timer);
}

Upvotes: 2

Abraham Uribe
Abraham Uribe

Reputation: 3118

you can try to use setTimeout on the animate callback

var fadeDuration=2000;
var slideDuration=2000;//change this to work 2000 after animate ends
var currentIndex=1;
var nextIndex=1;
$(document).ready(function()
{
    $('ul.slideshow li').css({opacity: 0.0});
    $("'ul.slideshow li:nth-child("+nextIndex+")'").addClass('show').animate({opacity: 1.0}, fadeDuration);
    setTimeout('nextSlide()',slideDuration);
})
function nextSlide(){
    nextIndex =currentIndex+1;
    if(nextIndex > $('ul.slideshow li').length)
    {
        nextIndex =1;
    }
    $("'ul.slideshow li:nth-child("+nextIndex+")'").addClass('show').animate({opacity: 1.0}, fadeDuration);
    $("'ul.slideshow li:nth-child("+currentIndex+")'").animate({opacity: 0.0}, fadeDuration,function(){
        setTimeout('nextSlide()',slideDuration);//add setTimeout on callback
}).removeClass('show');
    currentIndex = nextIndex;
}

Upvotes: 0

Jonny Sooter
Jonny Sooter

Reputation: 2417

Does it matter? From what I can tell, only the pictures change and the text (which is the important part) is still readable and doesn't change. I don't think the speed affects your slider much.

You can use a .resize() method to set the speed back when the window is resized. Or also use it to cancel the queue of events

var $window = $(window); //If you use a selection more than once, you should cache it.

$window.resize(function() {
    //Check if there has been a call already
    //If the check is true that means the code was already called
    //So we cancel any previous calls, this way the code is only called once
    if(this.resizeTO) clearTimeout(this.resizeTO);

    this.resizeTO = setTimeout(function() {
        $(this).trigger('lastResize'); //Call the actual code with a 500ms delay
    }, 500);
});

$window.on('lastResize', function() {
//This is a custom event that is triggered in the timeout
//This will only run on the last time the resize method was called
    $("ul.slideshow li").clearQueue();
});

Upvotes: 1

Related Questions