/** * 数字滚动工具 — 替代第三方库 * 用 setTimeout(fn, 16) 模拟 60fps,兼容性最稳 * 使用 easeOut 缓动: 1 - (1-t)^3 * * 使用: * const task = countUp({ from: 0, to: 30, duration: 800, onUpdate: setDisplayTime }) * // 不再需要时: * task.cancel() */ function countUp({ from = 0, to, duration = 800, decimals = 0, onUpdate, onComplete } = {}) { // 边界:数值相同 或 时长 <= 0,跳过动画 if (from === to || duration <= 0) { if (typeof onUpdate === 'function') onUpdate(to) if (typeof onComplete === 'function') onComplete() return { cancel: () => {} } } const start = Date.now() const delta = to - from let cancelled = false const tick = () => { if (cancelled) return const elapsed = Date.now() - start let t = Math.min(elapsed / duration, 1) // easeOut cubic t = 1 - Math.pow(1 - t, 3) const current = from + delta * t const value = decimals > 0 ? Number(current.toFixed(decimals)) : Math.round(current) if (typeof onUpdate === 'function') onUpdate(value) if (elapsed >= duration) { if (typeof onComplete === 'function') onComplete() return } setTimeout(tick, 16) } setTimeout(tick, 16) return { cancel() { cancelled = true } } } module.exports = { countUp }