Count animation from number A to B

后端 未结 8 948
一个人的身影
一个人的身影 2020-11-30 22:18

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

To make the whole thing a bit more alive,

相关标签:
8条回答
  • 2020-11-30 22:24

    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>

    0 讨论(0)
  • 2020-11-30 22:25

    I used a mixture of all of these to create a function that updates a BehaviorSubject.

    function animateValue(subject, timerRef, startValue, endValue, duration){
      if (timerRef) {  clearInterval(timerRef); }
      const minInterval = 100;
      const valueRange = endValue - startValue;
      const startTime = new Date().getTime();
      const endTime = startTime + (duration * 1000);
      const interval = Math.max((endTime-startTime)/valueRange, minInterval);
    
      function run() {
        const now = new Date().getTime();
        const rangePercent = Math.min(1-((endTime-now)/(endTime-startTime)),1);
        const value = Math.round(rangePercent * valueRange+startValue);
    
        subject.next(value);
        if (rangePercent >= 1) {
          clearInterval(timerRef);
        }
      }
    
      timerRef = setInterval(run, interval);
      run();
    }
    
    0 讨论(0)
  • 2020-11-30 22:34

    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>

    0 讨论(0)
  • 2020-11-30 22:40

    This works well. However, I needed to use a comma within the number. Below is the updated code which checks for commas. Hope someone finds this useful if they stumble across this post.

    function animateValue(id, start, end, duration) {
    
        // check for commas
        var isComma = /[0-9]+,[0-9]+/.test(end); 
        end = end.replace(/,/g, '');
    
        // 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);
            }
            // Preserve commas if input had commas
            if (isComma) {
                while (/(\d+)(\d{3})/.test(value.toString())) {
                    value = value.toString().replace(/(\d+)(\d{3})/, '$1'+','+'$2');
                }
            }
        }
    
        var timer = setInterval(run, stepTime);
        run();
    }
    
    animateValue("value", 100, 25, 2000); 
    
    0 讨论(0)
  • 2020-11-30 22:40

    HTML

    <!DOCTYPE html>
    <html>
    <head>
        <title>Count</title>
    </head>
    <body>
        <div id="value">1000</div>
    </body>
    </html>
    

    JAVASCRIPT snippet

    Here is a simple js function decrementing values from a given start number to an end number (object prototype)..

    function getCounter(startCount,endcount,time,html){
    objects = {
        //you can alternateif you want yo add till you reach the endcount
        startCount:startCount,
        endCount:endcount,
        timer:time
    }
    this.function = function(){
        let startTm  = objects.startCount,
            timer = objects.timer,
            endCount = objects.endCount;
            //if you want it to add a number just replace the -1 with +1
            /*and dont forget to change the values in the object prototype given a variable of counter*/
        let increament = startTm  < endCount ? 1:-1;
            timmer  = setInterval(function(){
                    startTm  += increament;
                    html.innerHTML = startTm ;
                    if(startTm  == endCount){
                        clearInterval(timmer);
                    }
                },timer);
       }
    }
    // input your startCount,endCount  the timer.....
    let doc = document.getElementById('value');
    
    let counter = new getCounter(1000,1,10,doc);
    //calling the function in the object
    counter.function();
    

    Check out this demo https://jsfiddle.net/NevilPaul2/LLk0bzvm/

    0 讨论(0)
  • 2020-11-30 22:44

    Here is one version where increments grow by some defined multiplier (mul). frameDelay is the time delay for each increment. This looks a bit better if you have values that camn

    function cAnimate(id, start, end, frameDelay = 100, mul = 1.2) {
        var obj = document.getElementById(id);
        var increment = 2;
        var current = start;
        var timer = setInterval(function() {
            current += increment;
            increment *= mul;
            if (current >= end) {
                current = end;
                clearInterval(timer);
            }
    
            obj.innerHTML = Math.floor(current).toLocaleString();
    
        }, frameDelay);
    }
    
    cAnimate("counter", 1, 260000, 50);
    
    0 讨论(0)
提交回复
热议问题