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