UNPKG

countdown-pro

Version:
310 lines (306 loc) 9.6 kB
'use strict'; /** * 前置补零,如果值的长度小于目标长度,则前置补零,否则不处理 * * @param num 待处理的值 * @param targetLength 目标长度 * @returns 补零后的值 */ function padZero(num, targetLength) { if (targetLength === void 0) { targetLength = 2; } var str = '' + num; while (str.length < targetLength) { str = '0' + str; } return str; } var SECOND = 1000; var MINUTE = 60 * SECOND; var HOUR = 60 * MINUTE; var DAY = 24 * HOUR; var mathFloor = Math.floor; /** * 解析时间戳 * * @param {number} timestamp 时间戳,单位毫秒 * @returns 包含日/时/分/秒/毫秒的对象 */ function parseTimeData(timestamp) { return { days: mathFloor(timestamp / DAY), hours: mathFloor((timestamp % DAY) / HOUR), minutes: mathFloor((timestamp % HOUR) / MINUTE), seconds: mathFloor((timestamp % MINUTE) / SECOND), milliseconds: mathFloor(timestamp % SECOND) }; } /** * 格式化时间格式 * * @param format 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒 * @param timeData 包含日/时/分/秒/毫秒的对象 * @returns 返回格式化后的时间字符串 */ function parseFormat(format, timeData) { // eslint-disable-next-line prefer-const var days = timeData.days, hours = timeData.hours, minutes = timeData.minutes, seconds = timeData.seconds, milliseconds = timeData.milliseconds; if (format.indexOf('DD') === -1) { hours += days * 24; } else { format = format.replace('DD', padZero(days)); } if (format.indexOf('HH') === -1) { minutes += hours * 60; } else { format = format.replace('HH', padZero(hours)); } if (format.indexOf('mm') === -1) { seconds += minutes * 60; } else { format = format.replace('mm', padZero(minutes)); } if (format.indexOf('ss') === -1) { milliseconds += seconds * 1000; } else { format = format.replace('ss', padZero(seconds)); } return format.replace('SSS', padZero(milliseconds, 3)); } /** * 格式化时间 * * @param {number} timestamp 时间戳,单位毫秒 * @param {string} [pattern='HH:mm:ss'] 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒。默认值为 HH:mm:ss * @returns {string} 返回格式化后的时间字符串 */ function format(timestamp, pattern) { if (pattern === void 0) { pattern = 'HH:mm:ss'; } var timeData = parseTimeData(timestamp); return parseFormat(pattern, timeData); } var noop = function () { }; var defaultInterval = 1000; /** * 倒计时 * * @param {Object} options 配置项 * @param {number} options.time 倒计时,单位毫秒 * @param {number} [options.interval=1000] 时间间隔,单位毫秒。默认 `1000` * @param {Function} [options.onChange] 倒计时时间变动时触发 * @param {Function} [options.onEnd] 倒计时结束时触发 * @param {number} [options.adjustInterval] 自动校准倒计时时间间隔,单位毫秒。如果有值且大于 `0`,再开始倒计时时会执行自动校准定时任务。暂定或结束倒计时会停止定时任务。 * @returns * @example * const countdown = new Countdown({ * time: 60 * 1000 * interval: 1000, * onChange(){}, * onEnd(){}, * adjustInterval: 10 * 1000 * }); * * // 实例方法 * // 开始倒计时 * countdown.start(); * * // 暂停倒计时 * countdown.pause(); * * // 重置倒计时。先暂停再将倒计时时间重置 * countdown.reset(); * * // 重置再开始倒计时 * countdown.restart(); * * // 更新配置。如果更新 `time` 需要手动调用 `reset` 或 `restart` 方法才生效 * countdown.updateOptions(options); * * // 校准倒计时。在倒计时运行时才生效,如果需要校准会先暂停再开始。 * countdown.adjustTime(); * * // 静态方法 * // 格式化时间,返回格式化后的时间字符串 * CountDown.format(2 * 60 * 60 * 1000); // "02:00:00" * CountDown.format(2 * 60 * 60 * 1000, 'mm:ss'); // "120:00" * * // 前置补零,返回补零后的值 * CountDown.padZero(2); // "02" * * // 解析时间戳,返回的时间对象格式 * CountDown.parseTimeData(2 * 60 * 60 * 1000); * // {days: 0, hours: 2, minutes: 0, seconds: 0, milliseconds: 0} * */ var CountDown = /** @class */ (function () { function CountDown(options) { this.options = this.o = { onChange: noop, onEnd: noop, interval: defaultInterval, time: 0, adjustInterval: 0 }; this.updateOptions(options); this.timer = null; this.counting = false; this.completed = false; this.currentTime = this.o.time; this.adjustStartTime = 0; this.adjustCurrentTime = 0; this.adjustTimer = null; } CountDown.prototype._handleEnd = function () { clearInterval(this.adjustTimer); this.counting = false; this.completed = true; this.o.onEnd(); }; /** * 更新配置。 * * 如果更新 `time` 需要手动调用 `reset` 或 `restart` 方法才生效。 * * @param {Object} options 配置项 * @param {number} [options.time] 倒计时,单位毫秒 * @param {number} [options.interval] 时间间隔,单位毫秒 * @param {Function} [options.onChange] 倒计时时间变动时触发 * @param {Function} [options.onEnd] 倒计时结束时触发 * @returns */ CountDown.prototype.updateOptions = function (options) { if (typeof options === 'object') { for (var prop in options) { // @ts-ignore if (options[prop] !== undefined) { // @ts-ignore this.o[prop] = options[prop]; } } } // 倒计时长 if (typeof this.o.time !== 'number' || this.o.time < 0) { this.o.time = 0; } // 倒计时间隔 if (typeof this.o.interval !== 'number' || this.o.interval < 0) { this.o.interval = defaultInterval; } }; /** * 开始倒计时 * @returns */ CountDown.prototype.start = function () { var _this = this; if (this.counting || this.completed) { return; } this.adjustStartTime = Date.now(); this.adjustCurrentTime = this.currentTime; if (this.o.adjustInterval > 0) { this.adjustTimer = setInterval(function () { _this.adjustTime(); }, this.o.adjustInterval); } this.counting = true; this.tick(); }; /** * 校准倒计时时间。建议使用 `adjustInterval` 配置。 * * 仅在倒计时运行时才生效。如果需要校准,会先暂停,调用 `onChange` ,再开始倒计时。 * * @example * const interval = 1000; * let timer = null; * const countdown = new CountDown({ * time: 60 * 1000, * interval, * onEnd(){ * clearInterval(timer); * } * }); * * // 每倒计时10次,校准一次倒计时时间 * const timer = setInterval(()=>{ * countdown.adjustTime(); * }, interval * 10); * */ CountDown.prototype.adjustTime = function () { if (this.counting) { var currentTimestamp = Date.now(); var diffTime = currentTimestamp - this.adjustStartTime; var diffTimeInt = Math.round(diffTime / this.o.interval) * this.o.interval; var newCurrentTime = this.adjustCurrentTime - diffTimeInt; if (newCurrentTime >= 0 && this.currentTime !== newCurrentTime) { this.pause(); this.currentTime = newCurrentTime; this.o.onChange(this.currentTime); if (this.currentTime === 0) { this._handleEnd(); } else { this.start(); } } } }; /** * 暂停倒计时 */ CountDown.prototype.pause = function () { if (this.counting) { clearTimeout(this.timer); clearInterval(this.adjustTimer); this.counting = false; } }; /** * 重置倒计时。 * * 先暂停再将倒计时时间重置。 */ CountDown.prototype.reset = function () { this.pause(); this.completed = false; if (this.currentTime !== this.o.time) { this.currentTime = this.o.time; this.o.onChange(this.currentTime); } }; /** * 重置再开始倒计时 */ CountDown.prototype.restart = function () { this.reset(); this.start(); }; CountDown.prototype.tick = function () { var _this = this; var interval = this.o.interval; this.timer = setTimeout(function () { _this.currentTime -= interval; if (_this.currentTime < 0) { _this.currentTime = 0; } _this.o.onChange(_this.currentTime); if (_this.currentTime === 0) { _this._handleEnd(); } else { _this.tick(); } }, interval); }; CountDown.format = format; CountDown.parseTimeData = parseTimeData; CountDown.parseFormat = parseFormat; CountDown.padZero = padZero; return CountDown; }()); module.exports = CountDown;