javascript数字加减动画通过requestanimationframe实现平滑过渡,支持线性插值、缓动函数(如easeoutcubic)、小数与千分位格式化,并可中断重启动及多数字同步驱动。

用 JavaScript 实现数字加减的动画过渡效果,核心是让数字从起始值平滑变化到目标值,而不是直接跳变。常用方法是结合 requestAnimationFrame 或定时器(如 setInterval)逐步更新显示值,并配合缓动函数提升视觉自然感。
基础实现:线性插值 + requestAnimationFrame
这是最推荐的方式,性能好、控制精准、无累积误差。
- 计算每帧应增加的差值(总差值 ÷ 预期帧数),再逐帧累加
- 使用
Math.round()或toFixed()控制小数位,避免浮点误差导致显示异常 - 用
requestAnimationFrame替代setTimeout,保证与屏幕刷新率同步
示例代码:
function animateNumber(element, start, end, duration = 300) {
const startTime = performance.now();
const totalChange = end - start;
<p>function step(currentTime) {
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1); // 归一化进度 [0, 1]</p><pre class="brush:php;toolbar:false;">// 线性插值:start + (end - start) * progress
const value = start + totalChange * progress;
element.textContent = Math.round(value); // 整数显示;若需小数,改用 value.toFixed(1)
if (progress <p>}</p><p>requestAnimationFrame(step);
}</p><p>// 调用:将 id="count" 的元素从 0 动画到 123
animateNumber(document.getElementById('count'), 0, 123, 400);</p>增强体验:添加缓动效果(如 easeOutCubic)
线性变化略显机械,加入缓动函数能让数字“先快后慢”,更符合真实感。
- 常见缓动公式如
easeOutCubic: 1 - Math.pow(1 - t, 3) - 只需把
progress替换为缓动后的值,其余逻辑不变 - 可封装成通用缓动工具,支持多种曲线(easeInQuad、easeInOutSine 等)
修改上面的 step 函数中这一行即可:
// 替换原来的 const progress = ... 这一行 const t = Math.min(elapsed / duration, 1); const eased = 1 - Math.pow(1 - t, 3); // easeOutCubic const value = start + totalChange * eased;
支持小数、千分位和格式化显示
实际业务中常需保留一位小数、加逗号分隔符或拼接单位(如 “¥”、“%”)。
- 显示前对数值做格式化,但参与计算的仍是原始数字
- 用
Intl.NumberFormat或正则处理千分位,避免手动字符串拼接出错 - 注意:格式化后的字符串不能直接用于下一次计算,要保持数据与视图分离
例如显示带千分位和一位小数:
const formatter = new Intl.NumberFormat('zh-CN', {
minimumFractionDigits: 1,
maximumFractionDigits: 1
});
element.textContent = `${formatter.format(value)} 万元`;
进阶技巧:中断与重启动、多数字联动
用户频繁触发时(如快速点击增减按钮),需防止动画叠加或状态错乱。
- 每次启动新动画前,用
cancelAnimationFrame清除上一个任务 - 保存当前动画的
id,便于管理生命周期 - 多个数字同步动画?统一用同一个
requestAnimationFrame驱动,共享时间戳,更省资源也更同步
简单中断示例:
let currentAnimationId = null;
<p>function animateNumber(...) {
if (currentAnimationId) {
cancelAnimationFrame(currentAnimationId);
}</p><p>function step(...) {
// ...动画逻辑
if (progress </p><p>currentAnimationId = requestAnimationFrame(step);
}</p>不复杂但容易忽略细节,关键是把“目标值”“当前帧时间”“插值逻辑”“DOM 更新”四者串稳,再按需叠加缓动和格式化。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











