简体   繁体   中英

JS Counter decrementing which should not have happened

Following is the code of a counter. The problem is it runs first time correct but every other time i hit the button the count in decremented. Like for first time 100, second time 45, third time 12 and so on !!!

i have set all values of variable to 0 at the end but still it runs the same way any solution?

<div>
    <button onclick="runAnimations()">Clients counter</button>
</h2>
<div class="panel">
    <ul>
        <li>
            <span data-count="250" class="countup">250</span>+

</li>
        <li>
            <span data-count="500" class="countup">500</span>+

    </li>
        <li>
            <span data-count="100" class="countup">100</span>+
    
    
</li>
    </ul>
</div>




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

animationDuration = 0;
frameDuration = 0;
totalFrames = 0;
easeOutQuad = 0;
animateCountUp = 0;
countTo = 0;
progress = 0;
runAnimations = 0;
currentCount = 0;
frame = 0;
countupEls = 0;

}; 

First of all, setting those values to 0 is not a good idea especially because most of them are const so it shouldn't even be possible. I think the problem with the code is that somehow the runAnimations function is called too early on the same elements and since you pick the current text of the element as the end number for the counter, if the animation is currently running for that element already it will just pick a lower number for the second run because that is what the innerHTML is at that moment. To make sure this doesn't happen it would be a better approach to store the number as a data attribute like <div data-count="100" class="countup"></div> and as that never changes unlike the innerHTML of the elements, you can make sure your code uses the correct value every run.

Problem is solved by doing as you said above.

<div data-count="100" class="countup"></div>

const countTo = parseInt( el.getAttribute('data-count'), 10 );

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