/**
* 本模块提供倒数功能。
* @module countdown
*/
const computes = [
{ divisor: 24 * 60 * 60, unit: 'days' },
{ divisor: 60 * 60, unit: 'hours' },
{ divisor: 60, unit: 'minutes' },
{ divisor: 1, unit: 'seconds' }
];
/**
* 倒计时回调函数。
* @callback countdownCallback
* @memberof module:countdown.Countdown
* @param {Object} rest 剩余的时间。
* @param {number} rest.days 剩余天数。
* @param {number} rest.hours 剩余小时数。
* @param {number} rest.minutes 剩余分钟数。
* @param {number} rest.seconds 剩余秒数。
* @param {boolean} rest.totalMsecs 剩余的总毫秒数。
*/
/**
* 倒计时类。
* @memberof module:countdown
* @class
* @name Countdown
* @author luoliquan
* @param {number} secs 总秒数。
* @param {countdownCallback} [cb] 回调函数。
* @example
* const countdown = new Countdown(60, (rest) => {
* console.dir(rest);
* });
* countdown.start();
*/
export default class Countdown {
constructor(secs, cb) {
secs = parseInt(secs);
if (isNaN(secs)) { throw new Error('Total seconds must be a number'); }
this._secs = secs * 1000; // 倒计时毫秒数
this._cb = typeof cb === 'function' ? cb : function() {}; // 倒计时回调函数
}
_exec() {
if (!this._startTime) { return; }
let value = Math.max(0, this._secs - (Date.now() - this._startTime));
if (value > 0 && !this._stopped) {
setTimeout(() => { this._exec(); }, 1000);
}
if (value >= 0) {
const rest = {
totalMsecs: value
};
value = Math.round(value / 1000);
computes.forEach((item, i) => {
rest[item.unit] = value / item.divisor;
if (i === computes.length - 1) {
rest[item.unit] = Math.round(rest[item.unit]);
} else {
rest[item.unit] = Math.floor(rest[item.unit]);
value = value % item.divisor;
}
});
this._cb(rest);
}
}
/**
* 开始倒计时。
* @method
* @memberof module:countdown.Countdown.prototype
*/
start() {
if (this.secs <= 0) { return; }
this._startTime = Date.now();
this._exec();
}
/**
* 停止倒计时。
* @method
* @memberof module:countdown.Countdown.prototype
*/
stop() {
if (this._timerId) { clearTimeout(this._timerId); }
this._stopped = true;
}
}