При использовании setInterval, если я переключаю вкладки в Chrome и возвращаюсь назад, слайдер сходит с ума, догоняя - PullRequest
45 голосов
/ 31 мая 2011

У меня есть слайдер jQuery на моем сайте, и код, переходящий к следующему слайду, находится в функции под названием nextImage. Я использовал setInterval для запуска моей функции по таймеру, и он делает именно то, что я хочу: он запускает мои слайды по таймеру. НО, если я захожу на сайт в Chrome, переключаюсь на другую вкладку и возвращаюсь, слайдер непрерывно пробегает слайды, пока не «догонит». Кто-нибудь знает способ исправить это. Ниже мой код.

setInterval(function() {
nextImage();
}, 8000);

Ответы [ 6 ]

38 голосов
/ 31 мая 2011

Как определить, когда вкладка находится в фокусе или нет в Chrome с Javascript?

window.addEventListener('focus', function() {
    document.title = 'focused';
},false);

window.addEventListener('blur', function() {
    document.title = 'not focused';
},false);

Чтобы применить к вашей ситуации:

var autopager;
function startAutopager() {
    autopager = window.setInterval(nextImage, 8000);
}
function stopAutopager() {
    window.clearInterval(autopager);
}

window.addEventListener('focus', startAutopager);    
window.addEventListener('blur', stopAutopager);

Обратите внимание, что в последней версии Chromium есть либо ошибка, либо «особенность», которая делает ее менее надежной, требуя, чтобы пользователь щелкнул хотя бы один раз в любом месте окна. См. Связанный вопрос выше для деталей.

15 голосов
/ 12 сентября 2011

Я отправляю ответ здесь: Как заставить setInterval также работать, когда вкладка неактивна в Chrome?

Просто сделайте это:

setInterval(function() {
    $("#your-image-container").stop(true,true);
    nextImage();

}, 1000);

неактивновкладки браузера буферизуют некоторые функции setInterval или setTimeout.stop (true, true) - остановит все буферизованные события и сразу же выполнит только последнюю анимацию.

Метод window.setTimeout () теперь ограничивает передачу не более одного тайм-аута в секунду в неактивных вкладках.Кроме того, теперь он ограничивает вложенные тайм-ауты наименьшим значением, допустимым спецификацией HTML5: 4 мс (вместо 10 мс, которые он использовал для зажима).

6 голосов
/ 31 мая 2011

На ум приходит несколько идей:


Идея # 1

Вы можете сделать так, чтобы короткий взрыв был идемпотентным .Например, вы можете сказать:

function now() {
    return (new Date()).getTime();
}

var autopagerInterval = 8000;

function startAutopager() {
    var startImage = getCurrentImageNumber();
    var startTime = now();

    var autopager = setInterval(
        function() {
            var timeSinceStart = now() - startTime();
            var targetImage = getCurrentImageNumber + Math.ceil(timeSinceStart/autopagerInterval);
            if (getCurrentImageNumber() != targetImage)
                setImageNumber(targetImage);  // trigger animation, etc.
        },
        autopagerInterval
    );
    return autopager;
}

Таким образом, даже если функция выполняется 1000 раз, она все равно будет работать всего за несколько миллисекунд и анимироваться только один раз.

note: Если пользователь покидает страницу и возвращается, она будет прокручена.Вероятно, это не то, чего хочет оригинальный постер, но я оставляю это решение, поскольку иногда это то, что вы хотите.


Идея # 2

Еще один способ добавить идемпотентность (пока ещесохранение вашей функции nextImage() и отсутствие ее прокрутки вниз страницы) означало бы, что функция установила блокировку мьютекса, которая исчезает через секунду (очищается другим таймаутом).Таким образом, даже если функция setInterval была вызвана 1000 раз, будет запущен только первый экземпляр, а остальные ничего не сделают.

var locked = false;
var autopager = window.setInterval(function(){
    if (!locked) {
        locked = true;
        window.setTimeout(function(){
            locked=false;
        }, 1000);
        nextImage();
    }
}, 8000);

edit: это может не сработать, см. Ниже


Идея # 3

Я попробовал следующий тест:

function f() {
    console.log((new Date()) + window.focus());
    window.setTimeout(f, 1000);
}
f();

Кажется, это указывает на то, что функция вызывается каждую секунду.Это странно ... но я думаю, что это означает, что обратные вызовы вызывают , но рендерер отказывается обновлять страницу любым графическим способом, пока вкладка не сфокусирована,задержка всех операций до тех пор, пока пользователь не вернется, но операции продолжают накапливаться.

Также функция window.focus() не сообщает, имеет ли окно фокус;он дает фокус на окно и, таким образом, не имеет значения.

Вероятно, нам нужно следующее: Как определить, фокусируется ли вкладка или нет в Chrome с помощью Javascript? - вы можетесбросьте интервал, когда окно теряет фокус (размытие), и сбросьте его, когда оно получает фокус.

1 голос
/ 09 августа 2011

Я не знаю точно, что происходит в вашей функции nextImage (), но у меня была похожая проблема. Я использовал animate () с setInterval () на созданном мною слайдере изображений jQuery, и я чувствовал то же самое, что и вы, когда переключался на другую вкладку и возвращался снова. В моем случае функция animate () была поставлена ​​в очередь, поэтому, как только окно вернулось к фокусу, слайдер сошел с ума. Чтобы это исправить, я просто остановил функцию animate () в очереди.

Есть несколько способов сделать это. самый простой - с .stop (), но эта проблема и способы ее устранения описаны в документации по jQuery. Проверьте эту страницу внизу под заголовком дополнительных примечаний: http://api.jquery.com/animate/

0 голосов
/ 14 сентября 2011

Если вы используете слайдер изображений Soh Tanaka, просто добавьте это ..., чтобы решить вашу проблему с Google Chrome:

$(".image_reel").stop(true, true).fadeOut(300).animate({ left: -image_reelPosition}, 500 ).fadeIn(300);

Обратите внимание на функцию .stop ().Не обращайте внимания на появление и исчезновение, вот что я использовал в своей версии

Спасибо

0 голосов
/ 29 июля 2011

Я столкнулся с подобной проблемой, так или иначе этот код ниже работает для меня нормально.

            var t1= window.setInterval('autoScroll()', 8000);

    window.addEventListener('focus', function() {
        focused = true;
        window.clearInterval(t1);
        t1 = window.setInterval('autoScroll()', 8000);
    },false);

    window.addEventListener('blur', function() {
        focused = false;
        window.clearInterval(t1);
    },false)



function autoScroll()

    {

        if ( running == true){
            if ( focused = true){
                forwardSlide();
            }


        }

        else {

            running = true;

        }



    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...