css 从开始到结束值设置计数器动画

aiqt4smr  于 2023-05-30  发布在  其他
关注(0)|答案(2)|浏览(404)

我想在我的网站上放一个计数器。
下面的代码适用于非常大的数字,但像3或95.5这样的小数字不起作用。但是它可以处理超过1000的数字。你认为JavaScript代码的问题在哪里?
感谢您的指导。

const counters = document.querySelectorAll('.count');
const speed = 200;
counters.forEach((counter) => {
  const updateCount = () => {
  const target = parseInt(counter.getAttribute('data-target'));
    const count = parseInt(counter.innerText);
    const increment = Math.trunc(target / speed);
    if (count < target) {
       counter.innerText = count + increment;
       setTimeout(updateCount, 1);
    } else {
       counter.innerText = target;
    }
  };
 updateCount();
});
<div>
  <div class="counter">
    <div class="counter--inner">
       <span>+</span>
       <span data-target="3" class="count">0</span>
       <span>Years</span>
    </div>
    <p>example1</p>                     
  </div>
  
  <div class="counter">
    <div class="counter--inner">
       <span>+</span>
       <span data-target="50000" class="count">0</span>
    </div>
    <p>example2</p>                     
  </div>
  
  <div class="counter">
    <div class="counter--inner">
      <span data-target="95" class="count">0</span>
      <span>%</span>
    </div>
    <p>example3</p>                     
  </div>
  
  <div class="counter">
    <div class="counter--inner">
       <span data-target="10000" class="count">0</span>
      <span>%</span>
    </div>
    <p>example4</p>                     
  </div>
</div>
mutmk8jj

mutmk8jj1#

***MDN文档:***Math.trunc()函数返回整数部分,去掉小数位。

Math.trunc(target / 200)

  • target必须至少是200,才能最终获得1。但是你总是得到一个0,你试图做一个0 + 0

什么不该做

*不要在每次循环迭代时使用textContent从DOM节点抓取值。简单地,递增一个整数变量

  • 切勿使用设置为小毫秒值的setTimeout/setInterval()。这将阻塞main thread,并且您的应用程序性能可能会受到影响。更糟糕的是,如果此操作针对单个页面上的多个元素。
    *不要在不同的计时持续时间设置不同计数器的动画。一个合适的实现是在一个恒定的时间内动画所有计数器,从010或从09999999应该在恒定的持续时间期间 “动画” -以便用户感知这些视觉线索/变化并理解它,对于多个 * 计数器 * 元素。

在定义的时间段内对范围进行动画处理

这里有一个关于如何使用JavaScript正确创建动画计数器的防弹示例:

  • 使用适当的、更高性能的requestAnimationFrame(而不是setTimeout或setInterval)来避免主线程陷入困境。
  • 使用具有[data-counter]属性的元素。计数器将textContent视为起始值,并计数到存储在实际data-counter属性中的结束值
    • 向上 * 或 * 向下 * 计数-取决于开始/结束值
  • 如果 start 值等于 end 值,则不计数
const counter = (EL) => {

  const duration = 4000; // Animate all counters equally for a better UX

  const start = parseInt(EL.textContent, 10); // Get start and end values
  const end = parseInt(EL.dataset.counter, 10); // PS: Use always the radix 10!

  if (start === end) return; // If equal values, stop here.

  const range = end - start; // Get the range
  let curr = start; // Set current at start position
  
  const timeStart = Date.now();

  const loop = () => {
    let elaps = Date.now() - timeStart;
    if (elaps > duration) elaps = duration; // Stop the loop
    const frac = elaps / duration; // Get the time fraction
    const step = frac * range; // Calculate the value step
    curr = start + step; // Increment or Decrement current value
    EL.textContent = Math.trunc(curr); // Apply to UI as integer
    if (elaps < duration) requestAnimationFrame(loop); // Loop
  };

  requestAnimationFrame(loop); // Start the loop!
};

document.querySelectorAll("[data-counter]").forEach(counter);
<br>Count from 0 to 10
<br><span data-counter="10">0</span>
<br>You don't necessarily have to start at 0
<br><span data-counter="2022">1000</span>
<br>You can also count in reverse
<br><span data-counter="0">9999</span>
<br>or even to negative values
<br><span data-counter="-1000">1000</span>
<br>This one will not count
<br><span data-counter="666">666</span>
<br>
<br>And for a better UX - all the counters finished simultaneously  during 4000ms
a0x5cqrl

a0x5cqrl2#

你在尝试增加零。

const increment = Math.trunc(target / speed);

当你的目标小于200(这是你的硬编码速度)时,它将返回0。
Math.trunc(3/200)将为0,因为根据MDN Web文档:
函数的作用是:通过删除所有小数位数,返回一个数字的整数部分。https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
这就是为什么它不会对低于200的数字起作用。
您可以做的是删除Math.trunc并增加这些十进制值。

相关问题