How to prevent this code from running on every scroll

I would like to run the updateCount function every time I scroll past the id elements. However, it musts not run again when I keep scrolling.

Here is my code:

class Counter {
  constructor(id, target, speed, appendString) {
    this.id = id;
    this.target = target;
    this.speed = speed;
    this.appendString = appendString;
  }

  start() {
    const container = document.querySelector(this.id);
    container.innerText = 0;
    let count = 0;

    function updateCount(counter, target, speed, appendString) {
      if (count < target) {
        counter.innerText = `${count} ${appendString}`;
        count++;
        setTimeout(
          () => updateCount(counter, target, speed, appendString),
          speed
        );
      } else {
        counter.innerText = `${target} ${appendString}`;
      }
    }

    updateCount(container, this.target, this.speed, this.appendString);
  }
}

const counter1 = new Counter('#headline-e6423da8', 156, 15, '');
const counter2 = new Counter('#headline-77ad9299', 227, 15, '');
const counter3 = new Counter('#headline-8255ec52', 91, 15, '%');
const counter4 = new Counter('#headline-5e08a0cb', 30, 15, '+');

window.addEventListener('scroll', () => {
  counter1.start();
  counter2.start();
  counter3.start();
  counter4.start();
});

I didn’t really try to figure out what exactly it is you want to achieve but something like the Intersection Observer API might be worth looking at.

If you search for “Intersection Observer API” you can find more articles/tutorials/videos.

Thanks for your suggestion.

Indeed, this code updates numbers when scrolling. However, it updates them on every scroll when we keep scrolling. I would like this updateCount function to update the numbers when we reach the id elements on the viewport, but to prevent it from running again when we keep scrolling.

I tried this code with the Intersection Observer API, but it is still updating the numbers on every scroll. Here is the code:

<script>
  class Counter {
  constructor(id, target, speed, appendString) {
    this.id = id;
    this.target = target;
    this.speed = speed;
    this.appendString = appendString;
  }

  start() {
    const container = document.querySelector(this.id);
    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].intersectionRatio > 0) {
          container.innerText = 0;
          let count = 0;

          function updateCount(counter, target, speed, appendString) {
            if (count < target) {
              counter.innerText = `${count} ${appendString}`;
              count++;
              setTimeout(
                () => updateCount(counter, target, speed, appendString),
                speed
              );
            } else {
              counter.innerText = `${target} ${appendString}`;
            }
          }

          updateCount(container, this.target, this.speed, this.appendString);
        }
      },
      {
        root: null,
        threshold: 0.5,
      }
    );
    observer.observe(container);
  }
}

const counter1 = new Counter('#headline-e6423da8', 156, 15, '');
const counter2 = new Counter('#headline-77ad9299', 227, 15, '');
const counter3 = new Counter('#headline-8255ec52', 91, 15, '%');
const counter4 = new Counter('#headline-5e08a0cb', 30, 15, '+');

window.addEventListener('scroll', () => {
  counter1.start();
  counter2.start();
  counter3.start();
  counter4.start();
});
</script>