滚动触发数字计数特效(自研 JS,时长/起始值/重复触发可调)

JSCSS 许可:自研原创

滚动触发数字计数:数字进入视口时从 0 平滑递增到目标值,支持小数/千分位/后缀,动画时长与起始值可调,可一次性或重复触发,零依赖。

效果演示(真实可交互)

🎯 向下滚动,数字进入视口时从 0 开始计数

继续向下滚动 ↓
0精选组件
0好评率
0注册用户
0成立年份
↑ 数字已触发

演示区用内嵌滚动容器模拟页面滚动;正式使用时把 root 设为 null 即作用于页面视口。

完整代码

<div class="stat" data-target="1024" data-suffix="+"><b>0</b><span>精选组件</span></div>
<div class="stat" data-target="98.6" data-decimals="1" data-suffix="%"><b>0</b><span>好评率</span></div>
const easeOutCubic = t => 1 - Math.pow(1 - t, 3);

function runCount(el, dur = 1800) {
  const target = parseFloat(el.dataset.target);
  const decimals = parseInt(el.dataset.decimals || '0', 10);
  const suffix = el.dataset.suffix || '';
  const b = el.querySelector('b');
  const t0 = performance.now();
  const fmt = v => decimals === 0
    ? Number(v.toFixed(0)).toLocaleString('en-US')  // 千分位 36,000
    : v.toFixed(decimals);
  const tick = now => {
    const t = Math.min((now - t0) / dur, 1);
    b.textContent = fmt(target * easeOutCubic(t)) + suffix;
    if (t < 1) requestAnimationFrame(tick);
  };
  requestAnimationFrame(tick);
}

const observer = new IntersectionObserver(entries => {
  for (const en of entries) {
    if (en.isIntersecting) {
      runCount(en.target);
      observer.unobserve(en.target); // 去掉这行 = 每次进入视口都重新计数
    }
  }
}, { threshold: 0.5 });
document.querySelectorAll('.stat').forEach(el => observer.observe(el));

数据驱动:目标值、小数位、后缀全部写在 data-* 属性里,HTML 里直接配数据,JS 零改动即可复用。

参数说明

参数位置说明
目标值data-target计数终值,支持整数与小数
小数位data-decimals0 时自动加千分位分隔符
后缀data-suffix如 +、%、万,显示在数字后
动画时长runCount(el, dur)300-4000ms,默认 1800ms
起始值计数起点演示面板可调,默认从 0 开始
触发阈值threshold: 0.5元素可见一半才触发
触发模式unobserve()一次触发 / 移除后重复触发

兼容性与性能

常见问题

Q: 和 countUp.js 比有什么优势? countUp.js 虽在安全池,但本组件为粤喵自研实现:数据走 data-* 属性声明、自带千分位与小数格式化、按需观察自动释放,代码量更少且行为完全可控,无版本升级风险。

Q: 数字到顶后想四舍五入而不是截断怎么办? 用 Math.round(v) 替代 toFixed(0) 即可;小数场景 toFixed(decimals) 本身已按四舍五入处理。

Q: 同一个数字想每次滚动进入都重新计数? 去掉 observer.unobserve(en.target),并在元素离开视口时把 <b> 内容重置为起始值(演示面板勾选「仅触发一次」即可对比两种模式)。

Q: 可以商用吗? 可以。本组件为粤喵自研原创实现,免费商用无需署名,可自由修改。

许可与来源

  • 许可证:自研原创 —— 粤喵自研原创,可免费用于个人与商业项目,无需署名。查看来源公示与许可清单
  • 来源:粤喵团队原创自研(从效果思路到代码实现均为独立完成,未直接复制第三方代码)
  • 首次发布:2026-09-01 · 最近更新:2026-09-01
  • 修改日志:2026-09-01 首次发布;2026-09-13 补充许可证与来源标注、复制按钮说明与法务页入口
  • 纠错:联系页面 / min@cactus.asia,2 个工作日内核实处理

常见问题

这个组件可以商用吗?

可以。本组件为粤喵自研原创,可免费用于个人和商业项目,无需署名。

浏览器兼容性如何?

支持所有现代浏览器(Chrome / Firefox / Safari / Edge 最新版本)。旧版 IE 不支持 CSS 动画相关特性。

怎么修改动画参数?

直接调整 CSS 中的 animation-duration(时长)、animation-timing-function(缓动曲线)等属性即可,代码中有注释说明。

✍️ 作者与审核