Lors de l'utilisation de setInterval, si je change les onglets dans Chrome et que je reviens, le slider devient fou à rattraper

j'ai un slider jQuery sur mon site et le code allant à la diapositive suivante est dans une fonction appelée nextImage. J'ai utilisé setInterval pour exécuter ma fonction sur une minuterie, et il fait exactement ce que je veux: il exécute mes diapos sur une minuterie. Mais, si je vais sur le site dans Chrome, passer à un autre onglet et revenir, le curseur fonctionne à travers les diapositives en continu jusqu'à ce qu'il "rattrape". Quelqu'un sait-il d'un moyen de résoudre ce problème. Voici mon code.

setInterval(function() {
nextImage();
}, 8000);
45
demandé sur Nathan Shubert 2011-05-31 09:44:14

6 réponses

comment détecter quand un onglet est focalisé ou non dans Chrome avec Javascript?

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

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

pour s'appliquer à votre situation:

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

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

notez que dans la dernière version de Chromium, il y a soit un bug, soit une 'fonctionnalité' qui rend ce système moins fiable, exigeant que l'utilisateur ait cliqué au moins une fois n'importe où dans la fenêtre. Voir la question liée ci-dessus pour plus de détails.

38
répondu ninjagecko 2017-05-23 12:25:57

je poste une réponse ici: Comment puis-je faire fonctionner setInterval aussi quand un onglet est inactif dans Chrome?

faites Simplement ceci:

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

}, 1000);

onglets de navigateur inactifs buffer certaines des fonctions setInterval ou setTimeout. stop (true, true) - arrêtera tous les événements tamponnés et exécutera immadietly seulement la dernière animation.

la fenêtre.la méthode setTimeout() clamps maintenant pour envoyer pas plus d'un timeout par deuxième dans les onglets inactifs. De plus, il fixe maintenant les temps d'arrêt imbriqués à la plus petite valeur permise par la spécification HTML5: 4 ms (au lieu des 10 ms qu'il avait l'habitude de fixer).

15
répondu www 2017-05-23 12:02:14

quelques idées me viennent à l'esprit:


Idée n ° 1

Vous pouvez faire en sorte que d'une courte rafale est idempotent . Par exemple, vous pourriez dire:

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;
}

de cette façon, même si la fonction tourne 1000 fois, elle ne fonctionnera que quelques millisecondes et ne s'animera qu'une seule fois.

note : si l'utilisateur quitte la page et vient de retour, il aura défiler. Ce n'est probablement pas ce que l'affiche originale veut, mais je laisse cette solution depuis qu'il est parfois ce que vous voulez.


Idée n ° 2

une autre façon d'ajouter idempotence (tout en conservant votre fonction nextImage() et en ne la faisant pas défiler vers le bas de la page) serait d'avoir la fonction définie une serrure mutex qui disparaît après une seconde (effacée par un autre délai). Ainsi, même si l' la fonction setInterval a été appelée 1000 fois, seule la première instance fonctionnait et les autres ne faisaient rien.

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

edit: ne fonctionne pas, voir ci-dessous


Idée n ° 3

j'ai essayé le test suivant:

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

il semble indiquer que la fonction est appelée chaque seconde. C'est bizarre... mais je pense que cela signifie que l' les callbacks sont étant appelé, mais que le page renderer refuse de mettre à jour la page de n'importe quelle manière graphique pendant que l'onglet est non-focalisé, retardant toutes les opérations jusqu'à ce que l'utilisateur retourne, mais les opérations continuent l'empilage.

aussi la fonction window.focus() ne dit pas si la fenêtre a la mise au point; elle donne la mise au point à la fenêtre, et est donc hors de propos.

ce que nous voulons est probablement ceci: Comment faire détecter quand un onglet est focalisé ou pas dans Chrome avec Javascript? -- vous pouvez désactiver votre intervalle lorsque la fenêtre perd la mise au point (flou), et le réinitialiser lorsqu'elle gagne la mise au point.

6
répondu ninjagecko 2017-05-23 11:46:57

je ne sais pas exactement ce qui se passe dans votre fonction nextImage(), mais j'ai eu un problème similaire. J'utilisais animate() avec setInterval () sur un slider d'image jQuery que j'ai créé, et j'expérimentais la même chose que vous quand je suis passé à un onglet différent et de nouveau. Dans mon cas, la fonction animate() était mise en file d'attente, donc une fois la fenêtre recentrée, le curseur devenait fou. Pour corriger cela, j'ai juste arrêté la fonction animate() de faire la queue.

là existe quelques façons dont vous pouvez faire cette. le plus simple est avec .stop(), mais ce problème et les solutions pour y remédier sont documentées dans le jQuery docs. Vérifiez cette page près du bas sous la rubrique Notes supplémentaires: http://api.jquery.com/animate /

1
répondu 000justin000 2011-08-09 14:28:26

j'avais fait face à un problème similaire, en quelque sorte ce code ci-dessous fonctionne très bien pour moi.

            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;

        }



    }
0
répondu Maheshchandra Hegde 2011-07-29 16:30:55

si vous utilisez le curseur d'image de SOH Tanaka, ajoutez simplement ceci...pour résoudre votre problème Google Chrome:

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

prendre note du .fonction stop (). Ignorer les fluctuations des trucs, c'est ce que j'ai utilisé sur ma version

Merci

0
répondu Nasir 2011-09-14 15:54:20