2

I'm attempting to add a count up animation using javascript on my page. I've been able to get a working solution but the counter stops working if the number has a comma for example : 53,210 the counter will display 53. How can I be able to have the counter animation with numbers that have a comma?

Here is a code snippet :

window.onload = function() {
  runAnimations();
};

// How long you want the animation to take, in ms
const animationDuration = 2000;
// Calculate how long each ‘frame’ should last if we want to update the animation 60 times per second
const frameDuration = 1000 / 60;
// Use that to calculate how many frames we need to complete the animation
const totalFrames = Math.round( animationDuration / frameDuration );
// An ease-out function that slows the count as it progresses
const easeOutQuad = t => t * ( 2 - t );



// The animation function, which takes an Element
const animateCountUp = el => {
    let frame = 0;
    const countTo = parseInt( el.innerHTML, 10 );
    // Start the animation running 60 times per second
    const counter = setInterval( () => {
        frame++;
        // Calculate our progress as a value between 0 and 1
        // Pass that value to our easing function to get our
        // progress on a curve
        const progress = easeOutQuad( frame / totalFrames );
        // Use the progress value to calculate the current count
        const currentCount = Math.round( countTo * progress );

        // If the current count has changed, update the element
        if ( parseInt( el.innerHTML, 10 ) !== currentCount ) {
            el.innerHTML = currentCount;
        }

        // If we’ve reached our last frame, stop the animation
        if ( frame === totalFrames ) {
            clearInterval( counter );
        }
    }, frameDuration );
};


// Run the animation on all elements with a class of ‘countup’
const runAnimations = () => {
    const countupEls = document.querySelectorAll( '.countup' );
    countupEls.forEach( animateCountUp );
};
<ul>
  <li><span class="countup">45</span></li>
  <li><span class="countup">110</span></li>
  <li><span class="countup">53,210</span></li>
</ul>

I am expecting the HTML to display the full number of 53,210 with the count up animation. Not stop at the number before the comma.

kurtixl
  • 419
  • 4
  • 17
  • `integer` numbers do not have commas. You can display them in a human-readable format to make it easier to *see* the thousands, and millions, etc. but for computers, this is not needed. You could simply use a number w/o delimiters (commas) for the calculations and display them with delimiters for humans to see – blurfus Sep 17 '21 at 17:33

3 Answers3

2

Need to parseInt with comma. :

parseInt(el.innerHTML.replace(/,/g, ''), 10)

Also display with comma need to following line change.

el.innerHTML = currentCount.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");

Check following code.

window.onload = function() {
  runAnimations();
};

// How long you want the animation to take, in ms
const animationDuration = 2000;
// Calculate how long each ‘frame’ should last if we want to update the animation 60 times per second
const frameDuration = 1000 / 60;
// Use that to calculate how many frames we need to complete the animation
const totalFrames = Math.round( animationDuration / frameDuration );
// An ease-out function that slows the count as it progresses
const easeOutQuad = t => t * ( 2 - t );



// The animation function, which takes an Element
const animateCountUp = el => {
    let frame = 0;
    const countTo = parseInt(el.innerHTML.replace(/,/g, ''), 10);
    // Start the animation running 60 times per second
    const counter = setInterval( () => {
        frame++;
        // Calculate our progress as a value between 0 and 1
        // Pass that value to our easing function to get our
        // progress on a curve
        const progress = easeOutQuad( frame / totalFrames );
        // Use the progress value to calculate the current count
        const currentCount = Math.round( countTo * progress );

        // If the current count has changed, update the element
        if ( parseInt( el.innerHTML, 10 ) !== currentCount ) {
            el.innerHTML = currentCount.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
        }

        // If we’ve reached our last frame, stop the animation
        if ( frame === totalFrames ) {
            clearInterval( counter );
        }
    }, frameDuration );
};


// Run the animation on all elements with a class of ‘countup’
const runAnimations = () => {
    const countupEls = document.querySelectorAll( '.countup' );
    countupEls.forEach( animateCountUp );
};
<ul>
  <li><span class="countup">45</span></li>
  <li><span class="countup">110</span></li>
  <li><span class="countup">53,210</span></li>
</ul>
Malvik Bhavsar
  • 407
  • 5
  • 8
0

Add .toLocaleString('en-US'); to your const currentCount so that animation contain a comma according to US number system .
See this for .toLocaleString('en-US');

If you want to use comma in the class also than use .replace(',', '') to remove comma when function values are entered . Also if values contain more than 1 comma than use global attribute in like this .replace(/\,/g, '')
See this for Regular expressions

window.onload = function() {
  runAnimations();
};

// How long you want the animation to take, in ms
const animationDuration = 2000;
// Calculate how long each ‘frame’ should last if we want to update the animation 60 times per second
const frameDuration = 1000 / 60;
// Use that to calculate how many frames we need to complete the animation
const totalFrames = Math.round(animationDuration / frameDuration);
// An ease-out function that slows the count as it progresses
const easeOutQuad = t => t * (2 - t);



// The animation function, which takes an Element
const animateCountUp = el => {
  let frame = 0;
  const countTo = parseInt(el.innerHTML.replace(/\,/g, ''), 10);
  // Start the animation running 60 times per second
  const counter = setInterval(() => {
    frame++;
    // Calculate our progress as a value between 0 and 1
    // Pass that value to our easing function to get our
    // progress on a curve
    const progress = easeOutQuad(frame / totalFrames);
    // Use the progress value to calculate the current count
    const currentCount = Math.round(countTo * progress).toLocaleString('en-US');;

    // If the current count has changed, update the element
    if (parseInt(el.innerHTML, 10) !== currentCount) {
      el.innerHTML = currentCount;
    }

    // If we’ve reached our last frame, stop the animation
    if (frame === totalFrames) {
      clearInterval(counter);
    }
  }, frameDuration);
};


// Run the animation on all elements with a class of ‘countup’
const runAnimations = () => {
  const countupEls = document.querySelectorAll('.countup');
  countupEls.forEach(animateCountUp);
};
<ul>
  <li><span class="countup">45</span></li>
  <li><span class="countup">110</span></li>
  <li><span class="countup">53,210</span></li>
  <li><span class="countup">5,3,2,1,0</span></li>
  <li><span class="countup">53,215480</span></li>
</ul>
Rana
  • 2,500
  • 2
  • 7
  • 28
0

You could try to remove the , from the input before proceeding with the rest of the code. Something along the lines of:

  // get input as string from HTML
  const formattedNumber = el.innerHTML;
  
  // Format as number input (removes commas)
  const inputNumber = formattedNumber.replace(/\,/g,'');
  const countTo = new Number(inputNumber);
  

See demo

window.onload = function() {
  runAnimations();
};

// How long you want the animation to take, in ms
const animationDuration = 2000;
// Calculate how long each ‘frame’ should last if we want to update the animation 60 times per second
const frameDuration = 1000 / 60;
// Use that to calculate how many frames we need to complete the animation
const totalFrames = Math.round(animationDuration / frameDuration);
// An ease-out function that slows the count as it progresses
const easeOutQuad = t => t * (2 - t);



// The animation function, which takes an Element
const animateCountUp = el => {
  let frame = 0;
  
  // get input as string from HTML
  const formattedNumber = el.innerHTML;
  
  // Format as number input (removes commas)
  const inputNumber = formattedNumber.replace(/\,/g,'');
  const countTo = new Number(inputNumber);
  
  // Start the animation running 60 times per second
  const counter = setInterval(() => {
    frame++;
    // Calculate our progress as a value between 0 and 1
    // Pass that value to our easing function to get our
    // progress on a curve
    const progress = easeOutQuad(frame / totalFrames);
    // Use the progress value to calculate the current count
    const currentCount = Math.round(countTo * progress);

    // If the current count has changed, update the element
    if (parseInt(el.innerHTML, 10) !== currentCount) {
      el.innerHTML = currentCount;
    }

    // If we’ve reached our last frame, stop the animation
    if (frame === totalFrames) {
      clearInterval(counter);
    }
  }, frameDuration);
};


// Run the animation on all elements with a class of ‘countup’
const runAnimations = () => {
  const countupEls = document.querySelectorAll('.countup');
  countupEls.forEach(animateCountUp);
};
<ul>
  <li><span class="countup">45</span></li>
  <li><span class="countup">110</span></li>
  <li><span class="countup">53,210</span></li>
</ul>
blurfus
  • 13,485
  • 8
  • 55
  • 61