简体   繁体   中英

jQuery animated number counter from zero to value

I have created a script to animate a number from zero to it's value.

Working

jQuery

 $({ Counter: 0 }).animate({ Counter: $('.Single').text() }, { duration: 1000, easing: 'swing', step: function() { $('.Single').text(Math.ceil(this.Counter)); } });
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <span class="Single">150</span>


Not Working

I now want to run the script several times on the page for each matching class.

Below is what I am trying but with no success so far:

HTML

<span class="Count">200</span>
<span class="Count">55</span>

JQUERY

$('.Count').each(function () {
  jQuery({ Counter: 0 }).animate({ Counter: $(this).text() }, {
    duration: 1000,
    easing: 'swing',
    step: function () {
      $(this).text(Math.ceil(this.Counter));
    }
  });
});

Your this doesn't refer to the element in the step callback, instead you want to keep a reference to it at the beginning of your function (wrapped in $this in my example):

$('.Count').each(function () {
  var $this = $(this);
  jQuery({ Counter: 0 }).animate({ Counter: $this.text() }, {
    duration: 1000,
    easing: 'swing',
    step: function () {
      $this.text(Math.ceil(this.Counter));
    }
  });
});

Update : If you want to display decimal numbers, then instead of rounding the value with Math.ceil you can round up to 2 decimals for instance with value.toFixed(2) :

step: function () {
  $this.text(this.Counter.toFixed(2));
}

this inside the step callback isn't the element but the object passed to animate()

$('.Count').each(function (_, self) {
    jQuery({
        Counter: 0
    }).animate({
        Counter: $(self).text()
    }, {
        duration: 1000,
        easing: 'swing',
        step: function () {
            $(self).text(Math.ceil(this.Counter));
        }
    });
});

Another way to do this and keep the references to this would be

$('.Count').each(function () {
    $(this).prop('Counter',0).animate({
        Counter: $(this).text()
    }, {
        duration: 1000,
        easing: 'swing',
        step: function (now) {
            $(this).text(Math.ceil(now));
        }
    });
});

FIDDLE

IMPORTANT : It seems like a small difference but you should really use a data attribute to hold the original number to count up to. Altering the original number can have un-intended consequences. For instance, I'm having this animation run everytime an element enters the screen. But if the element enters, exits, and then enters the screen a second time before the first animation finishes, it will count up to the wrong number.

HTML:

<p class="count" data-value="200" >200</p>
<p class="count" data-value="70" >70</p>
<p class="count" data-value="32" >32</p>

JQuery:

$('.count').each(function () {
    $(this).prop('Counter', 0).animate({
            Counter: $(this).data('value')
        }, {
        duration: 1000,
        easing: 'swing',
        step: function (now) {                      
            $(this).text(this.Counter.toFixed(2));
        }
    });
});

What the code does, is that the number 8000 is counting up from 0 to 8000. The problem is, that it is placed at the middle of quite long page, and once user scroll down and actually see the number, the animation is already dine. I would like to trigger the counter, once it appears in the viewport.

JS:

$('.count').each(function () {
                $(this).prop('Counter',0).animate({
                        Counter: $(this).text()
                }, {
                        duration: 4000,
                        easing: 'swing',
                        step: function (now) {
                                $(this).text(Math.ceil(now));
                        }
                });
            });

And HTML:

 <span class="count">8000</span>

You can get the element itself in .each() , try this instead of using this

$('.Count').each(function (index, value) {
    jQuery({ Counter: 0 }).animate({ Counter: value.text() }, {
        duration: 1000,
        easing: 'swing',
        step: function () {
            value.text(Math.ceil(this.Counter));
        }
    });
});

This worked for me

HTML CODE

<span class="number-count">841</span>

jQuery Code

$('.number-count').each(function () {
    $(this).prop('Counter',0).animate({
        Counter: $(this).text()
    }, {
        duration: 4000,
        easing: 'swing',
        step: function (now) {
            $(this).text(Math.ceil(now));
        }
    });

Here is my solution and it's also working, when element shows into the viewport


You can see the code in action by clicking jfiddle

 var counterTeaserL = $('.go-counterTeaser'); var winHeight = $(window).height(); if (counterTeaserL.length) { var firEvent = false, objectPosTop = $('.go-counterTeaser').offset().top; //when element shows at bottom var elementViewInBottom = objectPosTop - winHeight; $(window).on('scroll', function() { var currentPosition = $(document).scrollTop(); //when element position starting in viewport if (currentPosition > elementViewInBottom && firEvent === false) { firEvent = true; animationCounter(); } }); } //counter function will animate by using external js also add seprator "." function animationCounter(){ $('.numberBlock h2').each(function () { var comma_separator_number_step = $.animateNumber.numberStepFactories.separator('.'); var counterValv = $(this).text(); $(this).animateNumber( { number: counterValv, numberStep: comma_separator_number_step } ); }); } https://jsfiddle.net/uosahmed/frLoxm34/9/ 

If you wanna handle based on if it is int or float

 $(".display-counter").each(function () { $(this) .prop("Counter", 0) .animate( { Counter: $(this).text() }, { duration: 4000, easing: "swing", step: function (now, tween) { // Check added for decimal number if(parseInt(tween.end) == parseFloat(tween.end)){ $(this).text(Math.ceil(now)); } else{ $(this).text(now.toFixed(2)); } }, } ); });
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <p class="display-counter">123</p> <p class="display-counter">125.3</p>

This is work for me !

<script type="text/javascript">
$(document).ready(function(){
        countnumber(0,40,"stat1",50);
        function countnumber(start,end,idtarget,duration){
            cc=setInterval(function(){
                if(start==end)
                {
                    $("#"+idtarget).html(start);
                    clearInterval(cc);
                }
                else
                {
                   $("#"+idtarget).html(start);
                   start++;
                }
            },duration);
        }
    });
</script>
<span id="span1"></span>

This is working for me

$('.Count').each(function () {
    $(this).prop('Counter',0).animate({
        Counter: $(this).text()
    }, {
        duration: 4000,
        easing: 'swing',
        step: function (now) {
            $(this).text(Math.ceil(now));
        }
    });
});

  
 
  
  
    $({ Counter: 0 }).animate({
      Counter: $('.Single').text()
    }, {
      duration: 1000,
      easing: 'swing',
      step: function() {
        $('.Single').text(Math.ceil(this.Counter));
      }
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <span class="Single">150</span>

You can do it with animate function in jQuery.

$({ countNum: $('.code').html() }).animate({ countNum: 4000 }, {
    duration: 8000,
    easing: 'linear',
    step: function () {
        $('.yourelement').html(Math.floor(this.countNum));
    },
    complete: function () {
        $('.code').html(this.countNum);
        //alert('finished');
   }
});

Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM