首页 > 解决方案 > 滚动到视口时的动画计数器 - 带有千位分隔符

问题描述

这个问题的脚本对我来说非常有用,直到我有需要包含数千个分隔符的数字。现在我得到一个错误“NAN”。我需要分隔符在那里。不知道如何解决这个问题。我能想到的唯一(hacky)的事情是只计算分隔符之间的每个组,所以对于 1,160,868,它就像

<span class="count">1</span>,<span class="count">160</span>,<span class="count">868</span>




// Counter animation
// inViewport jQuery plugin
// http://stackoverflow.com/a/26831113/383904
$(function($, win) {
   $.fn.inViewport = function(cb) {
      return this.each(function(i,el){
         function visPx(){
            var H = $(this).height(),
            r = el.getBoundingClientRect(), t=r.top, b=r.bottom;
            return cb.call(el, Math.max(0, t>0? H-t : (b<H?b:H)));
         } visPx();
         $(win).on("resize scroll", visPx);
      });
   };
}(jQuery, window));

jQuery(function($) { // DOM ready and $ in scope
   $(".count").inViewport(function(px) { // Make use of the `px` argument!!!

      // if element entered V.port ( px>0 ) and
      // if prop initNumAnim flag is not yet set
      //  = Animate numbers
      if(px>0 && !this.initNumAnim) {
         this.initNumAnim = true; // Set flag to true to prevent re-running the same animation
         $(this).prop('Counter',0).animate({
            Counter: $(this).text()
         }, {
            duration: 4000,
            step: function (now) {
               $(this).text(Math.ceil(now));
            }
         });
      }
   });
});
// end Counter animation

从技术上讲,这会起作用。如果这是我需要这样做的方式,我会的。但是对于我的后端团队来说,当他们从数据库中提取这些数字时,能够使用逗号分隔符获取数字会容易得多。

标签: javascriptjquery

解决方案


要获得数千- 逗号分隔的字符串,请使用Number.prototype。toLocaleString ( )

console.log( (12345678).toLocaleString('en-US') );

在视口中时动画

对于您的具体情况,我可能会建议使用IntersectionObserver API ,而不是使用我在这个答案中的旧inViewport代码片段。

如果您需要将作为单独的 SPAN 元素- 拆分toLocaleStringat 逗号的结果,将每个值包装成 a <span>,最后join(",")将 Array 包装回字符串:

const animNum = (EL) => {
  
  if (EL._isAnimated) return; // Animate only once!
  EL._isAnimated = true;
  
  $(EL).prop('Counter', 0).animate({
    Counter: EL.dataset.num
  }, {
    duration: 3000,
    step: function(now) {
      const text = (Math.ceil(now)).toLocaleString('en-US');
      const html = text.split(",").map(n => `<span class="count">${n}</span>`).join(",");
      $(this).html(html);
    }
  });
};

const inViewport = (entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) animNum(entry.target);
  });
};

$("[data-num]").each((i, EL) => {
  const observer = new IntersectionObserver(inViewport);
  observer.observe(EL);
});
.count {
  font-size: 1.5em;
  color: fuchsia;
}
<p style="height: 200vh;">Scroll down....... This one will animate only once</p>
<div data-num="12345678"></div>
<p style="height: 200vh;">Scroll down....... The next one will always animate</p>
<div data-num="7536712"></div>
<p style="height: 100vh;">That's it!</p>

<script src="https://code.jquery.com/jquery-3.6.0.js"></script>


推荐阅读