Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count animation from number A to B

Tags:

javascript

css

I am updating a numeric value inside an element by doing intervalled ajax requests.

To make the whole thing a bit more alive, I want to count from the current value to the new one, by partially in- or decreasing the value over a time of n sec.

So basically something like this:

<div id="value">100</div> <script type="text/javascript">     /** Decrease $value (over a time of 2 seconds) till it reaches 25 */     $value.increaseAnimation(-75, {duration:2}); </script> 

Is there a javascript library for doing so?

like image 662
RienNeVaPlu͢s Avatar asked Jun 08 '13 00:06

RienNeVaPlu͢s


People also ask

How do you make an animated counter in HTML?

In the HTML body tag, specify the div tag with an id. Add JavaScript code to the script tag. Use the setInterval() method to execute the update function which will increment the count value. Get the id using the getElementById() method and use the innerHTML property to display the count.


2 Answers

You can just code it yourself pretty simply:

function animateValue(id, start, end, duration) {     if (start === end) return;     var range = end - start;     var current = start;     var increment = end > start? 1 : -1;     var stepTime = Math.abs(Math.floor(duration / range));     var obj = document.getElementById(id);     var timer = setInterval(function() {         current += increment;         obj.innerHTML = current;         if (current == end) {             clearInterval(timer);         }     }, stepTime); }  animateValue("value", 100, 25, 5000);
#value {     font-size: 50px; }
<div id="value">100</div>

Here's is a more accurate version that self adjusts in case the timer intervals aren't perfectly accurate (which they sometimes aren't):

function animateValue(id, start, end, duration) {     // assumes integer values for start and end          var obj = document.getElementById(id);     var range = end - start;     // no timer shorter than 50ms (not really visible any way)     var minTimer = 50;     // calc step time to show all interediate values     var stepTime = Math.abs(Math.floor(duration / range));          // never go below minTimer     stepTime = Math.max(stepTime, minTimer);          // get current time and calculate desired end time     var startTime = new Date().getTime();     var endTime = startTime + duration;     var timer;        function run() {         var now = new Date().getTime();         var remaining = Math.max((endTime - now) / duration, 0);         var value = Math.round(end - (remaining * range));         obj.innerHTML = value;         if (value == end) {             clearInterval(timer);         }     }          timer = setInterval(run, stepTime);     run(); }  animateValue("value", 100, 25, 5000);
#value {     font-size: 50px; }
<div id="value">100</div>
like image 193
jfriend00 Avatar answered Sep 23 '22 21:09

jfriend00


Current solutions do update more often than needed. Here a frame based approach, which is accurate:

function animateValue(obj, start, end, duration) {    let startTimestamp = null;    const step = (timestamp) => {      if (!startTimestamp) startTimestamp = timestamp;      const progress = Math.min((timestamp - startTimestamp) / duration, 1);      obj.innerHTML = Math.floor(progress * (end - start) + start);      if (progress < 1) {        window.requestAnimationFrame(step);      }    };    window.requestAnimationFrame(step);  }    const obj = document.getElementById('value');  animateValue(obj, 100, -25, 2000);
div {font-size: 50px;}
<div id="value">100</div>
like image 31
User Rebo Avatar answered Sep 24 '22 21:09

User Rebo