2009-10-28 5 views
0

J'essaye d'installer une fonction dans JavaScript pour fondre ou fondu dehors quelques éléments sur ma page. Le fondu fonctionne bien, mais mon problème se produit quand l'un d'eux essaie d'annuler les actions de l'autre.Annuler une boucle temporisée en JavaScript?

//I know this is ugly, I'm just learning JavaScript again and plan to recode it after I learn some more... 
var fadeOut = false 

//set out to true to fade out, false to fade in 
function fade(out) { 
    var steps = 1 
    var outSpeed = 100 
    var inSpeed = 10 
    var timer = 0 

    if (out) { 
      //fade out 
      fadeOut = true 
      for (var i=100; i>=0; i-=steps) { 
        if (fadeOut) { 
          setTimeout("set_el_opacity(" + (i/100) + ")", 
          timer+=steps 
        } else { 
          break; 
        } 
      } 
    } else { 
      //fade in 
      fadeOut = false 
      for (var i=0; i<=100; i+=steps) { 
        if(!fadeOut) { 
          setTimeout("set_el_opacity(" + (i/100) + ")", 
          timer+=steps 
        } else { 
          break; 
        } 
      } 
    } 
} 

Maintenant, le fondu est configuré pour fonctionner plus lentement que le fondu. Je veux que l'utilisateur de voir se faner lentement afin qu'ils sachent qu'il est sur le but, puis disparaître de nouveau dans rapidement si les éléments sont nécessaires (enlever un peu d'encombrement de l'écran quand ce n'est pas nécessaire).

fondu (vrai) fonctionne bien, fondu (faux) fonctionne bien et est plus rapide. Mon problème se produit lorsque j'appelle fade (true) suivi par fade (false). Les fondus se battent entre eux puis, puisque l'appel de fondu (vrai) s'exécute plus vite, il finit en premier et l'appel de fondu (faux) continue à disparaître complètement.

Ma question est: que puis-je faire pour que l'appel fade (false) annule la boucle de l'appel fade (true)?

+0

** Astuce **: Ne jamais passer une chaîne comme argument à 'setTimeout' /' setInterval'. Si vous l'utilisez en production, votre site peut être vulnérable à [XSS] (http://en.wikipedia.org/wiki/Cross-site_scripting "Cross-site scripting"). Utilisez une * fonction anonyme * à la place: 'setTimeout (fonction() {set_el_opacity (i/100);}, 1000);' – nyuszika7h

Répondre

0

Pour commencer, ce n'est pas une bonne idée de déclencher beaucoup de minuteurs dans une boucle. Vous devez plutôt utiliser setInterval ou déclencher une nouvelle minuterie à partir de votre gestionnaire setTimeout.

Une autre approche consiste à avoir une seule minuterie qui se déclenche à intervalles fixes et gère tous les effets en attente. Vous pouvez décider d'une fréquence d'images et laisser votre minuterie (une "pile de minuterie") fonctionner indéfiniment, "cocher" à chaque image - vous pouvez éventuellement démarrer/arrêter le ticking lorsqu'il n'y a pas d'effets en attente.

+0

C'est ce que j'avais besoin de réaliser. J'adaptais du code que j'avais trouvé en ligne et je ne m'étais pas rendu compte que la fonction setTimeout revenait immédiatement. Donc, fondamentalement, cette boucle met en place environ 100 temporisateurs d'intervalles plus longs et les laisse ensuite se déclencher. Je pourrais les attribuer à un tableau et les annuler tous, ou mieux encore, refaire le code pour regarder correctement. Merci – Geek42

7

Lorsque vous réglez la minuterie:

mytime = setTimeout('function()', 1000); 

vous pouvez l'annuler en utilisant clearTimeout:

clearTimeout(mytime); 
+0

Merci, cela répond à ma question. Le commentaire sur setInterval ci-dessous me fait savoir que je devrais refaire le code pour fonctionner différemment et plus efficacement. – Geek42

0

Vous devez annuler le délai d'attente actif chaque fois fade() est appelé, en utilisant la fonction clearTimeout(). Pour plus d'informations sur les délais d'attente, consultez this article. Voici un bref exemple basé sur le code que vous avez fourni.

var timeoutId = null; 

function fade(out) { 
    // ... 
    // Your variable declarations 
    // ... 

    // Cancel the active timeout, if any. 
    clearTimeout(timeoutId); 

    // Record the timeout ID inside your if-else blocks 
    if (out) { 
     // ... 
     timeoutId = setTimeout(...); 
     // ... 
    } else { 
     // ... 
     timeoutId = setTimeout(...); 
     // ... 
    } 
} 
+0

'clearTimeout', pas' cancelTimeout': https://developer.mozilla.org/fr/DOM/window.clearTimeout – NickFitz

+0

oups, merci pour la correction –

0

Simpliest MANIPULER TIMEOUT WAY LOOP

function myFunc (terminator = false) { 
    if(terminator) { 
     clearTimeout(timeOutVar); 
    } else { 
     // do something 
     console.log("loop"); 
     timeOutVar = setTimeout(function(){myFunc();}, 1000); 
    } 
} 
myFunc(true); // -> start loop 
myFunc(false); // -> end loop