滚动跑马灯计数组件(滚动距离驱动计数器,速度/方向/目标可调)
滚动跑马灯计数组件:自研 JS requestAnimationFrame 驱动无缝跑马灯,滚动累积距离实时驱动数字计数器,速度、方向、目标值可调,离开视口自动暂停省电,零依赖。
效果演示(真实可交互)
🏁 跑马灯滚动累积距离,驱动计数器数值(满值自动循环复位)
完整代码
实现思路:跑马灯内容复制一份形成无缝循环,用 requestAnimationFrame 按速度逐帧移动,同时累计「已滚动距离」;计数器 = 距离 ÷ 步长,其中步长 = 半程宽度 ÷ 目标值,满值后取模循环复位——滚动越快,计数越快,两者天然联动。
<div class="count" id="count">000000</div>
<div class="stage" id="stage">
<div class="track" id="track">
<span class="chip">✦ 粤喵组件站</span>
<span class="chip">纯 CSS</span>
<span class="chip">3D 动效</span>
<span class="chip">✦</span>
</div>
</div>
.stage { overflow: hidden; border-radius: 999px; background: #0f1117; padding: 14px 0; }
.track { display: flex; gap: 14px; width: max-content; will-change: transform; }
.chip { padding: 10px 22px; border-radius: 999px; background: #1a2030;
border: 1px solid #2f3a52; color: #cdd3e0; white-space: nowrap; }
const track = document.getElementById('track');
const stage = document.getElementById('stage');
track.innerHTML += track.innerHTML; // 复制一份内容 → 无缝循环
const half = track.scrollWidth / 2; // 半程宽度
let pos = 0, dist = 0, last = 0;
function tick(t) {
const dt = Math.min((t - last) / 1000, 0.05);
last = t;
pos -= 90 * dt; // 90 = 速度 px/s
if (pos <= -half) pos += half; // 循环复位
dist += 90 * dt; // 累计滚动距离
const step = half / 888888; // 步长 = 半程 / 目标值
const count = Math.floor(dist / step) % 888889;
document.getElementById('count').textContent =
String(count).padStart(6, '0');
track.style.transform = 'translateX(' + pos.toFixed(2) + 'px)';
requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
参数说明
| 参数 | 位置 | 说明 |
|---|---|---|
| 滚动速度 | tick 中的 90 | px/s,演示中 20-240 可调 |
| 滚动方向 | pos -= dir * speed * dt | dir 为 1 向左、-1 向右 |
| 目标值 | step = half / target | 跑完半程对应的计数峰值,演示中最大 999999 |
| 循环复位 | pos <= -half 与取模 | 内容与计数均自动循环 |
| 暂停策略 | IntersectionObserver | 离开视口自动停帧,回来自动续跑 |
兼容性与性能
- 全程仅操作
transform与文本节点,transform 由 GPU 合成,60fps 下开销可控 - 文本更新使用
textContent而非 innerHTML,避免触发重解析 - 复制内容采用一次性的
innerHTML +=,仅初始化时执行一次 - 离开视口时通过 IntersectionObserver 取消动画帧,移动端显著省电
- 现代浏览器全支持;老浏览器仅退化为静止文本条,不影响内容展示
- 目标值上限 999999,计数以 6 位补零显示,视觉上类似里程表
常见问题
Q: 跑马灯首尾接不上、出现跳变怎么办? 确保内容宽度超过容器宽度,且 gap 在复制前后保持一致。本实现直接复制整份内容再以半程宽度取模,天然无缝;若自定义内容,请保持两份完全一致。
Q: 计数与滚动不同步是什么原因? 计数器由「距离」而非「帧数」驱动,理论上严格同步;若出现偏差,检查是否把 dt 换算成了秒((t - last) / 1000),并限制最大 dt 防止切后台后跳帧。
Q: 如何让计数只增不减、不做循环? 去掉取模运算 % (target + 1),并把循环复位逻辑改为「仅内容回绕、距离继续累加」,即可变成一直增长的里程表效果。
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(缓动曲线)等属性即可,代码中有注释说明。