【问题标题】:Large numbers in count-up show NaN in safari browsersafari 浏览器中的大量计数显示 NaN
【发布时间】:2021-05-28 16:16:10
【问题描述】:

我在 Vanilla JS 中创建了一个计数函数。一切正常。当您向下滚动到它时,计数器就会启动。不幸的是,大数字 35 000 000 在 iOS Safari 浏览器中显示为 NaN。我不知道为什么。请帮忙。看起来大数字在 iOS Safari 浏览器中不起作用。

var animationDuration = 3000;
var frameDuration = 1000 / 60;
var totalFrames = Math.round(animationDuration / frameDuration);
var easeOutQuad = t => t * (2 - t);
var animateCountUp = el => {
  let frame = 0;
  var countTo = parseInt(el.innerHTML.replace(/ /g, ''), 10);
  var counter = setInterval(() => {
    frame++;
    var progress = easeOutQuad(frame / totalFrames);
    var currentCount = Math.round(countTo * progress);
    if (parseInt(el.innerHTML, 10) !== currentCount) {
      el.textContent = currentCount.toLocaleString().replace(/,/g, ' ');
    }
    if (frame === totalFrames) {
      clearInterval(counter);
    }
  }, frameDuration);
};
var count = document.querySelectorAll('.countup'),
  once = 1;
document.addEventListener('scroll', function() {
  if (once == 1 && count[0].getBoundingClientRect().top < window.innerHeight) {
    once = 0;
    count.forEach(animateCountUp);
  }
});
<div style="position: fixed">
    <span class="countup">12 500</span>
    <span class="countup">35 000 000</span>
</div>
<div style="height: 5000px"></div>

【问题讨论】:

  • 欢迎来到 Stack Overflow!我已将您的 HTML 和 JavaScript 复制到 Stack Snippet 中([&lt;&gt;] 工具栏按钮); here's how to do one,但它似乎没有做任何事情。您能否更新它以使其成为minimal reproducible example,并提供有关如何查看问题的说明?我认为它需要一些东西来滚动,但我不想猜测你真正使用的是什么。
  • 非常感谢。在我看来,它在这种情况下不起作用,因为它无法滚动。
  • 现在,有了 p 标签,它就可以工作了。
  • 刚刚在 Safari 14.0.3 中尝试过,它似乎可以按预期工作。
  • 我在 ios 14.4 上的移动 safari 上进行了测试,它仅在大数字中显示 NaN

标签: javascript mobile-safari nan


【解决方案1】:

为什么不使用counto 而不是使用DOM 作为存储来存储要计数的数字?

正如 TJ 所说,问题在于 Safari 在使用 innerHTML 而不是 textContent 时处理您的号码

if (currentCount<=countTo) {
  el.textContent = currentCount.toLocaleString().replace(/,/g, ' ');
}

在 iOS 14.4 上测试

https://plungjan.name/SO/tl.html

var animationDuration = 3000;
var frameDuration = 1000 / 60;
var totalFrames = Math.round(animationDuration / frameDuration);
var easeOutQuad = t => t * (2 - t);
var animateCountUp = el => {
  let frame = 0;
  var countTo = parseInt(el.textContent.replace(/ /g, ''), 10); // do not use innerHTML here
  var counter = setInterval(() => {
    frame++;
    var progress = easeOutQuad(frame / totalFrames);
    var currentCount = Math.round(countTo * progress);
    if (currentCount<=countTo) {
      el.textContent = currentCount.toLocaleString().replace(/,/g, ' ');
    }
    if (frame === totalFrames) {
      clearInterval(counter);
    }
  }, frameDuration);
};
var count = document.querySelectorAll('.countup'),
  once = 1;
document.addEventListener('scroll', function() {
  if (once == 1 && count[0].getBoundingClientRect().top < window.innerHeight) {
    once = 0;
    count.forEach(animateCountUp);
  }
});
<div style="position: fixed">
    <span class="countup">12 500</span>
    <span class="countup">35 000 000</span>
</div>
<div style="height: 5000px"></div>

【讨论】:

  • 是的,现在可以了。
【解决方案2】:

为此使用innerHTML 不太理想,实际上iOS Safari 正在为您的大量数字添加标记,这会影响您的代码。它将其识别为电话号码并将该元素的内部 HTML 更改为:&lt;a href="tel:35 000 000"&gt;35 000 000&lt;/a&gt;。这非常令人惊讶,但您可以在这里看到:

console.log(document.querySelector(".countup").innerHTML);
&lt;span class="countup"&gt;35 000 000&lt;/span&gt;

注意:据我所知仅适用于 iOS Safari。

使用textContent 代替有效,因为文本没有改变:

var animationDuration = 3000;
var frameDuration = 1000 / 60;
var totalFrames = Math.round(animationDuration / frameDuration);
var easeOutQuad = t => t * (2 - t);
var animateCountUp = el => {
  let frame = 0;
  var countTo = parseInt(el.textContent.replace(/ /g, ''), 10);
  var counter = setInterval(() => {
    frame++;
    var progress = easeOutQuad(frame / totalFrames);
    var currentCount = Math.round(countTo * progress);
    if (parseInt(el.textContent, 10) !== currentCount) {
      el.textContent = currentCount.toLocaleString().replace(/,/g, ' ');
    }
    if (frame === totalFrames) {
      clearInterval(counter);
    }
  }, frameDuration);
};
var count = document.querySelectorAll('.countup'),
  once = 1;
document.addEventListener('scroll', function() {
  if (once == 1 && count[0].getBoundingClientRect().top < window.innerHeight) {
    once = 0;
    count.forEach(animateCountUp);
  }
});
<div style="position: fixed">
    <span class="countup">12 500</span>
    <span class="countup">35 000 000</span>
</div>
<div style="height: 5000px"></div>

您也可以通过添加meta 标记为described in this question's answers 来告诉iOS Safari 不要这样做:

<meta name="format-detection" content="telephone=no">

但据我所知,这会在页面范围内禁用它。

【讨论】:

  • 这似乎不是很有效if (parseInt(el.textContent, 10) !== currentCount) { el.textContent = currentCount.toLocaleString().replace(/,/g, ' '); } - 为什么这不是一个不同的 var 而不是 textContent?
  • @mplungjan - 除了 NaN 问题,我什么也没做。
  • 原来是if (parseInt(el.innerHTML, 10) 所以如果我们根本不使用DOM作为存储,那么问题也已经解决了
  • @test - 我也没想到,我发现 iOS Safari 的这种行为非常令人惊讶。将数字显示为电话号码会很好,但实际上更改 DOM 以添加标记似乎......不太理想。 :-)
猜你喜欢
  • 1970-01-01
  • 2017-01-15
  • 2019-03-19
  • 1970-01-01
  • 2016-01-27
  • 1970-01-01
  • 2016-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多