JavaScript大数和小数计数器

4
我一直在为网页计数器工作,但是我卡在了这个无法解决的函数上。
我有一个包含4个div的计数器,由于其中两个是小数字,另外两个是大数字,因此前面的数字跑得非常快,以至于我无法观察到其功能。
有人知道如何设置JS函数以便它们可以以不同的速度运行,并且同时完成吗?

let section_counter = document.querySelector('#section_counter');
let counters = document.querySelectorAll('.counter-item .counter');

// Scroll Animation

let CounterObserver = new IntersectionObserver(
  (entries, observer) => {
    let [entry] = entries;
    if (!entry.isIntersecting) return;

    let speed = 1000;
    counters.forEach((counter, index) => {
      function UpdateCounter() {
        const targetNumber = +counter.dataset.target;
        const initialNumber = +counter.innerText;
        const incPerCount = targetNumber / speed;
        if (initialNumber < targetNumber) {
          counter.innerText = Math.ceil(initialNumber + incPerCount);
          setTimeout(UpdateCounter, 50);
        }
      }
        
      UpdateCounter();

      if (counter.parentElement.style.animation) {
        counter.parentElement.style.animation = '';
      } else {
        counter.parentElement.style.animation = `slide-up 0.3s ease forwards ${
          index / counters.length + 0.5
        }s`;
      }
    
    });
    observer.unobserve(section_counter);
  },
  {
    root: null,
    threshold: window.innerWidth > 768 ? 0.4 : 0.3,
  }
);

CounterObserver.observe(section_counter);
    <section id="section_counter">
      <div class="container">
        <h1 class="section-heading">For every set, you purchase of our sustainable wear, you are helping the world save: </h1>
      </div>
      <div class="container">
        <div class="counter-grid">
            
          <div class="counter-item">
            <h1 class="counter" data-target="15">0</h1>
            <h2 class="counter-heading">Plastic bottles</h2>
            <div class="counter-text">Which takes up to 150 years to decompose</div>
          </div>
          <div class="counter-item">
            <h1 class="counter" data-target="22">0</h1>
            <h2 class="counter-heading">KW of energy</h2>
            <div class="counter-text">Equivalent to 1-day household consumption</div>
          </div>
          <div class="counter-item">
            <h1 class="counter" data-target="5900">0</h1>
            <h2 class="counter-heading">Liters of water</h2>
            <div class="counter-text">Equivalent to the daily consumption of 16 persons (Mexico average)</div>

          </div>
          <div class="counter-item">
          <h1 class="counter" data-target="9000">0</h1>
          <h2 class="counter-heading">Grams of Co2 emissions</h2>
          <div class="counter-text">Equivalent to a 90 km car consumption</div>

          </div>
        </div>
      </div>
    </section>

1个回答

1
尝试使用附加属性"data-count"来解决问题。逻辑很简单:我们将带有小数值的计算结果存储在"data-count"中,然后只放置一个整数,最后删除"data-count"即可。

let section_counter = document.querySelector('#section_counter');
let counters = document.querySelectorAll('.counter-item .counter');

// Scroll Animation

let CounterObserver = new IntersectionObserver(
  (entries, observer) => {
    let [entry] = entries;
    if (!entry.isIntersecting) return;

    let speed = 1000;
    counters.forEach((counter, index) => {
      const targetNumber = +counter.dataset.target;
      // Find the unit for one counter step
      const count = targetNumber / speed;
      // Set data attribute for accurate calculation with decimal
      counter.setAttribute('data-count', 0);

      function UpdateCounter() {
        const initialNumber = +counter.innerText;
        // Get decimal number to calculate
        const countNumber = +counter.dataset.count;
        // Getting an integer value with Math.floor()
        const integer = Math.floor(countNumber);
        if (initialNumber < targetNumber) {
          // Set decimal number / toFixed() with speed length, to increase accuracy
          counter.setAttribute('data-count', (countNumber + count).toFixed(`${speed}`.length));
          // Set integer number
          counter.innerText = integer;
          setTimeout(UpdateCounter, 50);
        } else {
          // remove additional data attribute
          counter.removeAttribute('data-count');
        }
      }

      UpdateCounter();

      if (counter.parentElement.style.animation) {
        counter.parentElement.style.animation = '';
      } else {
        counter.parentElement.style.animation = `slide-up 0.3s ease forwards ${
            index / counters.length + 0.5
          }s`;
      }
    });
    observer.unobserve(section_counter);
  }, {
    root: null,
    threshold: window.innerWidth > 768 ? 0.4 : 0.3,
  }
);

CounterObserver.observe(section_counter);
<section id="section_counter">
  <div class="container">
    <h1 class="section-heading">
      For every set, you purchase of our sustainable wear, you are helping the world save:
    </h1>
  </div>
  <div class="container">
    <div class="counter-grid">
      <div class="counter-item">
        <h1 class="counter" data-target="15">0</h1>
        <h2 class="counter-heading">Plastic bottles</h2>
        <div class="counter-text">Which takes up to 150 years to decompose</div>
      </div>
      <div class="counter-item">
        <h1 class="counter" data-target="22">0</h1>
        <h2 class="counter-heading">KW of energy</h2>
        <div class="counter-text">Equivalent to 1-day household consumption</div>
      </div>
      <div class="counter-item">
        <h1 class="counter" data-target="5900">0</h1>
        <h2 class="counter-heading">Liters of water</h2>
        <div class="counter-text">
          Equivalent to the daily consumption of 16 persons (Mexico average)
        </div>
      </div>
      <div class="counter-item">
        <h1 class="counter" data-target="9000">0</h1>
        <h2 class="counter-heading">Grams of Co2 emissions</h2>
        <div class="counter-text">Equivalent to a 90 km car consumption</div>
      </div>
    </div>
  </div>
</section>


1
谢谢,Anton!你的解决方案完美无缺! - Mario Sosa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接