2010-02-25 3 views
4

J'ai un élément sur ma page que je voudrais augmenter de temps en temps:périodiquement Animer-up d'un numéro avec Javascript

<p class="count">28</p> 

Dans mon javascript, j'ai un intervalle qui fonctionne une fois 5 secondes et attrape de manière asynchrone le nouveau numéro (le plus élevé) du serveur. Cela fonctionne un peu dans le sens d'un compteur.

setInterval(function(){ 
    $.post("getcount.php", function(num){ 
    latestNum = num; 
    }); 
}, 5000); 

Si la requête asynchrone tire le numéro 56, je voudrais voir le changement de texte du paragraphe 28-56, montrant beaucoup (ou plus) ou les intermédiaires alors qu'il incrémente. Ce que je suis en train de faire est de définir un autre intervalle pour vérifier en permanence le texte du paragraphe, et la variable locale. Si le texte du paragraphe est inférieur à la valeur de la variable, il l'incrémente de 1. Il le fait toutes les demi-secondes.

setInterval(function(){ 
    currNum = Number($(".count").text()); 
    if (currNum < latestNum) 
    $(".count").text(currNum + 1); 
}, 50); 

Ma question est la suivante: Y at-il une meilleure façon de le faire sans avoir un intervalle constamment en cours d'exécution? Est-ce que j'invoque quelque chose que je peux invoquer à partir de la réponse d'une requête asynchrone, et que je l'arrête une fois que les deux nombres se sont rencontrés? Je dois également noter qu'il existe la possibilité que la prochaine demande ait lieu avant que les deux nombres aient été rapprochés en valeur.

Comment le collectif vous le faire?

Répondre

1

Voilà ma réponse - en fait deux réponses.
Faire un pas linéaire vers la valeur cible avec un intervalle fixe risque de ne jamais arriver.
Donc, j'ai aussi fourni une autre solution qui réduit la différence de moitié à chaque fois, y arrive beaucoup plus vite même pour de grandes différences.
Les deux exemples peuvent également compter.

$(function() { 

    var tRef, 
     counter = $('#counter'); 
     target = $('#target'); 

    /* 
    * A function that eases towards its target 
    */ 
    function convergeEasing(target) { 
     clearTimeout(tRef); 
     target = parseInt(target); 
     var current = parseInt(counter.html()); 
     var diff = target - current; 
     if(diff) { 
      var rounder = diff > 0 ? Math.ceil : Math.floor; 
      current += rounder(diff/2); 
      counter.html(current); 
      tRef = setTimeout(function() { 
       convergeEasing(target); 
      }, 250); 
     } 
    } 

    /* 
    * A function that plods towards its target 
    */ 
    function convergeLinear(target) { 
     clearTimeout(tRef); 
     target = parseInt(target); 
     var current = parseInt(counter.html()); 
     var diff = target - current; 
     if(diff) { 
      current += diff > 0 ? 1 : -1; 
      counter.html(current); 
      tRef = setTimeout(function() { 
       convergeLinear(target); 
      }, 250); 
     } 
    } 

    /* 
    * I've mocked your ajax request up here for demo purposes 
    * using the linear way as per your question 
    */ 
    setInterval(function(){ 
     var n = Math.round(Math.random()*1000); 
     target.html(n); 
     convergeLinear(n); 
    }, 5000); 

}); 

<div id="target">20</div> 
<div id="counter">20</div> 

Je suppose que la stratégie d'assouplissement pourrait être fonction qui est passé dans plutôt que les deux fonctions dupliquant une grande partie de leur code

2

corrigée Réponse:

Pour les commentateurs: avoir réalisé que moi-même ... encore merci! Cela enregistre l'intervalle dans une variable, puis appelle clearInterval pour arrêter l'intervalle. setTimeOut est nécessaire car sinon l'intervalle serait effacé lors de l'exécution.

Première réponse:

Pourquoi ne pas conjugons les deux fonctions, i.e. .:

setInterval(function(){ 
    $.post("getcount.php", function(num){ 
    latestNum = num; 
    if (currNum < latestNum) { 
     currNum = latestNum; 
     $(".count").text(currNum); 
    } 
    }); 
}, 5000); 

Cela permettrait d'éviter la mise à jour toutes les demi-secondes.

+0

Ouais, mais alors vous perdez l'animation de la mise à jour du numéro ... – marcgg

+0

Je veux animer à travers les intermédiaires. Cette approche remplacerait simplement la valeur actuelle par la nouvelle valeur. – Sampson

+0

c'est cool. L'avez-vous testé? – marcgg

0

Je reproduisais le deuxième intervalle lorsque le résultat était reçu et le terminais lorsque la valeur cible était atteinte.

1

En me basant sur la réponse Obalix, je recommanderais que l'intervalle de 5 secondes déclenche le plus petit intervalle.

var interval = null, currNum = null; 
setInterval(function(){ 
    $.post("getcount.php", function(num){ 
    latestNum = num; 
    if (currNum === null) 
     currNum = Number($(".count").text()); // should only execute once 
    if (currNum < latestNum && interval === null) 
     interval = setInterval(ObalixFunction, 50); 
    }); 
}, 5000); 

et modifier

function ObalixFunction() { 
    if (currNum < latestNum) { 
     // increment the currNum variable too so we don't have to keep parsing it 
     $(".count").text(++currNum); 
    } else { 
     setTimeOut(function() { clearInterval(interval); interval = null; }, 0); 
    } 
}