Files

50 lines
1.3 KiB
JavaScript

/**
* 数字滚动工具 — 替代第三方库
* 用 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 }