Периодическое оживление числа с помощью Javascript - PullRequest
4 голосов
/ 25 февраля 2010

На моей странице есть элемент, который я хотел бы время от времени увеличивать:

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

В моем javascript у меня есть интервал, который запускается каждые 5 секунд и асинхронно захватывает новый (более высокий) номер с сервера. Это работает в некотором роде по принципу счетчика.

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

Если асинхронный запрос сбрасывает число 56, я бы хотел, чтобы текст абзаца изменился с 28 на 56, показывая многие (или большинство) или промежуточные звенья при увеличении. В настоящее время я делаю еще один интервал для постоянной проверки текста абзаца и локальной переменной. Если текст абзаца меньше значения переменной, он увеличивает его на 1. Он делает это каждые полсекунды.

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

Мой вопрос таков: есть ли лучший способ сделать это без постоянного запуска интервала? Является ли это анимированным приращением чем-то, что я могу вызвать из ответа асинхронного запроса, а затем прекратить его, как только два числа встретятся в значении? Следует также отметить, что существует вероятность того, что следующий запрос будет выполнен до того, как два числа будут согласованы по значению.

Как бы коллектив вы сделали это?

Ответы [ 4 ]

2 голосов
/ 25 февраля 2010

Исправленный ответ:

Комментаторам: Я понял, что сам ... все еще спасибо!

var interval = setInterval(function(){
  currNum = Number( $(".count").text() );
  if (currNum < latestNum) {
    $(".count").text( currNum + 1 );
  } else {
    setTimeOut(function() { clearInterval(interval) }, 0);
  }
}, 50);

Это сохраняет интервал в переменной и затем вызывает clearInterval, чтобы остановить интервал. setTimeOut необходим, так как в противном случае интервал будет очищен при его выполнении.

Первый ответ:

Почему бы не объединить две функции, т. Е .:

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

Это предотвратит обновление каждые полсекунды.

1 голос
/ 25 февраля 2010

Вот мой ответ - на самом деле два ответа.
Линейный шаг к целевому значению с фиксированным интервалом может привести к тому, что вы туда никогда не дойдете.
Поэтому я также предоставил другое решение, которое каждый раз уменьшает вдвое разницу, гораздо быстрее, даже при больших различиях.
Оба примера также могут вести обратный отсчет.

$( 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>

Я полагаю, что стратегией ослабления может быть переданная функция, а не две функции, дублирующие большую часть их кода

1 голос
/ 25 февраля 2010

Опираясь на Obalix ответ, я бы рекомендовал, чтобы 5-секундный интервал вызывал меньший интервал.

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

и изменить

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);
    }
}
0 голосов
/ 25 февраля 2010

Я бы породил второй интервал, когда был получен результат, и завершил бы его, когда было достигнуто целевое значение.

...