requestAnimationFrame 介绍
Window:requestAnimationFrame() 方法 - Web API 接口参考 | MDN (mozilla.org)
代码封装
// CountDown.js
class CountDown {
constructor(remain) {
CountDown.remain = remain
this.change = () => null
}
static remain = null
static counting = false
static endTime = null
static rafId = null
start() {
CountDown.endTime = Date.now() + CountDown.remain
CountDown.counting = true
CountDown.count(this.change)
}
push() {
CountDown.counting = false
CountDown.cancelRaf(CountDown.refId)
}
static count(fn) {
CountDown.rafId = CountDown.raf(() => {
if (CountDown.counting) {
const currentRemain = CountDown.getRemain()
if (!CountDown.isTheSameSecond(currentRemain, CountDown.remain) || currentRemain === 0) {
CountDown.setRemain(currentRemain)
fn && fn(CountDown.parseTime(CountDown.remain))
}
if (CountDown.remain > 0) {
this.count(fn)
}
}
})
}
static getRemain() {
return Math.max(this.endTime - Date.now(), 0)
}
static setRemain(value) {
this.remain = value
}
// 是否同一秒
static isTheSameSecond(time1, time2) {
return Math.floor(time1 / 1000) === Math.floor(time2 / 1000)
}
// 格式化时间,输出天数时分秒
static parseTime(time) {
const SECOND = 1000;
const MINUTE = 60 * SECOND;
const HOUR = 60 * MINUTE;
const DAY = 24 * HOUR;
const days = Math.floor(time / DAY);
const hours = Math.floor((time % DAY) / HOUR);
const minutes = Math.floor((time % HOUR) / MINUTE);
const seconds = Math.floor((time % MINUTE) / SECOND);
const milliseconds = Math.floor(time % SECOND);
return {
total: time,
days,
hours,
minutes,
seconds,
milliseconds,
};
}
// 启用 requestAnimationFrame 倒计时
static raf(callback) {
return requestAnimationFrame(callback)
}
// 取消 requestAnimationFrame
static cancelRaf(id) {
cancelAnimationFrame(id)
}
}
使用
<button id="start">开始</button>
<button id="push">暂停</button>
<div>
剩余时间: <span id="days">0</span>天<span id="hours">0</span>时<span id="minutes">0</span>分<span id="seconds">0</span>秒
</div>
<script src="./CountDown.js">
const countDown = new CountDown(1000 * 60 * 60 * 24 * 60)
console.log(countDown)
countDown.change = (date) => {
console.log(date)
days.innerText = date.days
hours.innerText = date.hours
minutes.innerText = date.minutes
seconds.innerText = date.seconds
}
start.onclick = () => {
countDown.start()
}
push.onclick = () => {
countDown.push()
console.log(countDown)
}
</script>