feat: utils/countUp 数字滚动工具 (easeOut cubic)
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 数字滚动工具 — 替代第三方库
|
||||
* 用 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 }
|
||||
Reference in New Issue
Block a user