0

I was trying to make separate counters with separate increments, but it won't work. The code I now have works but the 3 counters have the same increment. My question is how can I code it so every counter has its own increment (and keeping it DRY).

const counter = function() {
  const counters = document.querySelectorAll(".counter");
  counters.forEach((counter) => {
    function updateCounter() {
      const target = +counter.getAttribute("data-target");
      const c = +counter.innerText;
      const increment = target / 500;

      if (c < target) {
        counter.innerText = `${Math.ceil(c + increment)}`;
        setTimeout(updateCounter, 1);
      } else {
        counter.innerText = target;
      }
    }
    updateCounter();
  });
}

counter();
<div class="counter" data-target="6"></div>
<div class="counter" data-target="6000"></div>
<div class="counter" data-target="12000"></div>

Hope you guys can help me out. :)

Thanks in advance!

Andy
  • 61,948
  • 13
  • 68
  • 95
Brontes
  • 35
  • 4

2 Answers2

0

When you log the values of increment, you can see that the interval is actually different for all of the three counters. However, the fact that the target value of the second counter is twice that of the third one means that the third counter will have twice as many iterations, but also twice the amount added per iteration, so they end up reaching their target at the same time. Take a smaller value for the second counter, e.g. 600, and you can see the difference.

For performance reasons, I would shift as many operations as possible out of the updateCounter() function if they don't need to be re-calculated each time, and also switch to requestAnimationFrame() instead of setTimeout().

const counter = function() {
  const counters = document.querySelectorAll(".counter");
  counters.forEach((counter) => {
    const target = +counter.getAttribute("data-target");
    const increment = target / 500;
    console.log(increment);

    function updateCounter() {
      const c = +counter.innerText;
      
      if (c < target) {
        counter.innerText = `${Math.ceil(c + increment)}`;
        window.requestAnimationFrame(updateCounter);
      } else {
        counter.innerText = target;
      }
    }
    updateCounter();
  });
}

counter();
<div class="counter" data-target="6"></div>
<div class="counter" data-target="600"></div>
<div class="counter" data-target="12000"></div>
Constantin Groß
  • 10,719
  • 4
  • 24
  • 50
-1

const makeCounter = (target, increment, start = 0, interval = 1) => {
  const div = document.createElement('div');
  let count = start;
  document.querySelector('body').appendChild(div);
  const handler = setInterval(() => {
    count += increment;
    if (count >= target) window.clearInterval(handler);
    div.innerText = count;
  },interval)
}

makeCounter(6, 1)
makeCounter(6000, 5)
makeCounter(12000, 15)
bel3atar
  • 913
  • 4
  • 6