countdown-pro
Advanced tools
+137
-10
@@ -89,2 +89,53 @@ 'use strict'; | ||
| 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 () { | ||
@@ -96,10 +147,30 @@ function CountDown(options) { | ||
| interval: defaultInterval, | ||
| time: 0 | ||
| time: 0, | ||
| adjustInterval: 0 | ||
| }; | ||
| this.updateOptions(options); | ||
| this.timer = null; // 定时器 | ||
| this.counting = false; // 标识正在倒计时 | ||
| this.completed = false; // 标识倒计时完成 | ||
| this.currentTime = this.o.time; // 记录当前倒计时长 | ||
| 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._onEnd = function () { | ||
| clearInterval(this.adjustTimer); | ||
| 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) { | ||
@@ -124,18 +195,72 @@ if (typeof options === 'object') { | ||
| }; | ||
| // 开始 | ||
| /** | ||
| * 开始倒计时 | ||
| * @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); | ||
| this.start(); | ||
| } | ||
| } | ||
| }; | ||
| /** | ||
| * 暂停倒计时 | ||
| */ | ||
| CountDown.prototype.pause = function () { | ||
| if (this.counting) { | ||
| clearTimeout(this.timer); | ||
| clearInterval(this.adjustTimer); | ||
| this.counting = false; | ||
| } | ||
| }; | ||
| // 重置 | ||
| /** | ||
| * 重置倒计时。 | ||
| * | ||
| * 先暂停再将倒计时时间重置。 | ||
| */ | ||
| CountDown.prototype.reset = function () { | ||
@@ -149,3 +274,5 @@ this.pause(); | ||
| }; | ||
| // 重新开始 | ||
| /** | ||
| * 重置再开始倒计时 | ||
| */ | ||
| CountDown.prototype.restart = function () { | ||
@@ -167,3 +294,3 @@ this.reset(); | ||
| _this.completed = true; | ||
| _this.o.onEnd(); | ||
| _this._onEnd(); | ||
| } | ||
@@ -170,0 +297,0 @@ else { |
+137
-10
@@ -87,2 +87,53 @@ /** | ||
| 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 () { | ||
@@ -94,10 +145,30 @@ function CountDown(options) { | ||
| interval: defaultInterval, | ||
| time: 0 | ||
| time: 0, | ||
| adjustInterval: 0 | ||
| }; | ||
| this.updateOptions(options); | ||
| this.timer = null; // 定时器 | ||
| this.counting = false; // 标识正在倒计时 | ||
| this.completed = false; // 标识倒计时完成 | ||
| this.currentTime = this.o.time; // 记录当前倒计时长 | ||
| 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._onEnd = function () { | ||
| clearInterval(this.adjustTimer); | ||
| 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) { | ||
@@ -122,18 +193,72 @@ if (typeof options === 'object') { | ||
| }; | ||
| // 开始 | ||
| /** | ||
| * 开始倒计时 | ||
| * @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); | ||
| this.start(); | ||
| } | ||
| } | ||
| }; | ||
| /** | ||
| * 暂停倒计时 | ||
| */ | ||
| CountDown.prototype.pause = function () { | ||
| if (this.counting) { | ||
| clearTimeout(this.timer); | ||
| clearInterval(this.adjustTimer); | ||
| this.counting = false; | ||
| } | ||
| }; | ||
| // 重置 | ||
| /** | ||
| * 重置倒计时。 | ||
| * | ||
| * 先暂停再将倒计时时间重置。 | ||
| */ | ||
| CountDown.prototype.reset = function () { | ||
@@ -147,3 +272,5 @@ this.pause(); | ||
| }; | ||
| // 重新开始 | ||
| /** | ||
| * 重置再开始倒计时 | ||
| */ | ||
| CountDown.prototype.restart = function () { | ||
@@ -165,3 +292,3 @@ this.reset(); | ||
| _this.completed = true; | ||
| _this.o.onEnd(); | ||
| _this._onEnd(); | ||
| } | ||
@@ -168,0 +295,0 @@ else { |
+137
-10
@@ -93,2 +93,53 @@ (function (global, factory) { | ||
| 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 () { | ||
@@ -100,10 +151,30 @@ function CountDown(options) { | ||
| interval: defaultInterval, | ||
| time: 0 | ||
| time: 0, | ||
| adjustInterval: 0 | ||
| }; | ||
| this.updateOptions(options); | ||
| this.timer = null; // 定时器 | ||
| this.counting = false; // 标识正在倒计时 | ||
| this.completed = false; // 标识倒计时完成 | ||
| this.currentTime = this.o.time; // 记录当前倒计时长 | ||
| 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._onEnd = function () { | ||
| clearInterval(this.adjustTimer); | ||
| 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) { | ||
@@ -128,18 +199,72 @@ if (typeof options === 'object') { | ||
| }; | ||
| // 开始 | ||
| /** | ||
| * 开始倒计时 | ||
| * @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); | ||
| this.start(); | ||
| } | ||
| } | ||
| }; | ||
| /** | ||
| * 暂停倒计时 | ||
| */ | ||
| CountDown.prototype.pause = function () { | ||
| if (this.counting) { | ||
| clearTimeout(this.timer); | ||
| clearInterval(this.adjustTimer); | ||
| this.counting = false; | ||
| } | ||
| }; | ||
| // 重置 | ||
| /** | ||
| * 重置倒计时。 | ||
| * | ||
| * 先暂停再将倒计时时间重置。 | ||
| */ | ||
| CountDown.prototype.reset = function () { | ||
@@ -153,3 +278,5 @@ this.pause(); | ||
| }; | ||
| // 重新开始 | ||
| /** | ||
| * 重置再开始倒计时 | ||
| */ | ||
| CountDown.prototype.restart = function () { | ||
@@ -171,3 +298,3 @@ this.reset(); | ||
| _this.completed = true; | ||
| _this.o.onEnd(); | ||
| _this._onEnd(); | ||
| } | ||
@@ -174,0 +301,0 @@ else { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"countdown.umd.js","sources":["../src/util.ts","../src/countdown.ts"],"sourcesContent":["/**\n * 前置补零,如果值的长度小于目标长度,则前置补零,否则不处理\n *\n * @param num 待处理的值\n * @param targetLength 目标长度\n * @returns 补零后的值\n */\nexport function padZero(num: string | number, targetLength = 2) {\n let str = '' + num;\n while (str.length < targetLength) {\n str = '0' + str;\n }\n return str;\n}\n\nconst SECOND = 1000;\nconst MINUTE = 60 * SECOND;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\n\nconst mathFloor = Math.floor;\n\n/**\n * 解析时间戳\n *\n * @param {number} timestamp 时间戳,单位毫秒\n * @returns 包含日/时/分/秒/毫秒的对象\n */\nexport function parseTimeData(timestamp: number) {\n return {\n days: mathFloor(timestamp / DAY),\n hours: mathFloor((timestamp % DAY) / HOUR),\n minutes: mathFloor((timestamp % HOUR) / MINUTE),\n seconds: mathFloor((timestamp % MINUTE) / SECOND),\n milliseconds: mathFloor(timestamp % SECOND)\n };\n}\n\n/**\n * 格式化时间格式\n *\n * @param format 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒\n * @param timeData 包含日/时/分/秒/毫秒的对象\n * @returns 返回格式化后的时间字符串\n */\nexport function parseFormat(format: string, timeData: ReturnType<typeof parseTimeData>) {\n // eslint-disable-next-line prefer-const\n let { days, hours, minutes, seconds, milliseconds } = timeData;\n\n if (format.indexOf('DD') === -1) {\n hours += days * 24;\n } else {\n format = format.replace('DD', padZero(days));\n }\n\n if (format.indexOf('HH') === -1) {\n minutes += hours * 60;\n } else {\n format = format.replace('HH', padZero(hours));\n }\n\n if (format.indexOf('mm') === -1) {\n seconds += minutes * 60;\n } else {\n format = format.replace('mm', padZero(minutes));\n }\n\n if (format.indexOf('ss') === -1) {\n milliseconds += seconds * 1000;\n } else {\n format = format.replace('ss', padZero(seconds));\n }\n\n return format.replace('SSS', padZero(milliseconds, 3));\n}\n\n/**\n * 格式化时间\n *\n * @param {number} timestamp 时间戳,单位毫秒\n * @param {string} [pattern='HH:mm:ss'] 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒。默认值为 HH:mm:ss\n * @returns {string} 返回格式化后的时间字符串\n */\nexport function format(timestamp: number, pattern = 'HH:mm:ss') {\n const timeData = parseTimeData(timestamp);\n return parseFormat(pattern, timeData);\n}\n\nexport const noop = () => {};\n","import { format, parseTimeData, parseFormat, padZero, noop } from './util';\n\nexport type Options = {\n time: number;\n interval?: number;\n onChange?: (currentTime: number) => void;\n onEnd?: () => void;\n};\n\nconst defaultInterval = 1000;\n\nclass CountDown {\n private o: Required<Options>; // alias\n protected options: Required<Options>;\n\n private timer: any;\n private counting: boolean;\n private completed: boolean;\n private currentTime: number;\n\n constructor(options: Options) {\n this.options = this.o = {\n onChange: noop,\n onEnd: noop,\n interval: defaultInterval,\n time: 0\n };\n\n this.updateOptions(options);\n\n this.timer = null; // 定时器\n this.counting = false; // 标识正在倒计时\n this.completed = false; // 标识倒计时完成\n this.currentTime = this.o.time; // 记录当前倒计时长\n }\n\n updateOptions(options: Partial<Options>) {\n if (typeof options === 'object') {\n for (const prop in options) {\n // @ts-ignore\n if (options[prop] !== undefined) {\n // @ts-ignore\n this.o[prop] = options[prop];\n }\n }\n }\n\n // 倒计时长\n if (typeof this.o.time !== 'number' || this.o.time < 0) {\n this.o.time = 0;\n }\n // 倒计时间隔\n if (typeof this.o.interval !== 'number' || this.o.interval < 0) {\n this.o.interval = defaultInterval;\n }\n }\n\n // 开始\n start() {\n if (this.counting || this.completed) {\n return;\n }\n\n this.counting = true;\n this.tick();\n }\n\n // 暂停\n pause() {\n if (this.counting) {\n clearTimeout(this.timer);\n this.counting = false;\n }\n }\n\n // 重置\n reset() {\n this.pause();\n this.completed = false;\n if (this.currentTime !== this.o.time) {\n this.currentTime = this.o.time;\n this.o.onChange(this.currentTime);\n }\n }\n\n // 重新开始\n restart() {\n this.reset();\n this.start();\n }\n\n private tick() {\n const interval = this.o.interval;\n\n this.timer = setTimeout(() => {\n this.currentTime -= interval;\n\n if (this.currentTime < 0) {\n this.currentTime = 0;\n }\n\n this.o.onChange(this.currentTime);\n\n if (this.currentTime === 0) {\n this.counting = false;\n this.completed = true;\n this.o.onEnd();\n } else {\n this.tick();\n }\n }, interval);\n }\n\n static format = format;\n static parseTimeData = parseTimeData;\n static parseFormat = parseFormat;\n static padZero = padZero;\n}\n\nexport default CountDown;\n"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"countdown.umd.js","sources":["../src/util.ts","../src/countdown.ts"],"sourcesContent":["/**\n * 前置补零,如果值的长度小于目标长度,则前置补零,否则不处理\n *\n * @param num 待处理的值\n * @param targetLength 目标长度\n * @returns 补零后的值\n */\nexport function padZero(num: string | number, targetLength = 2) {\n let str = '' + num;\n while (str.length < targetLength) {\n str = '0' + str;\n }\n return str;\n}\n\nconst SECOND = 1000;\nconst MINUTE = 60 * SECOND;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\n\nconst mathFloor = Math.floor;\n\n/**\n * 解析时间戳\n *\n * @param {number} timestamp 时间戳,单位毫秒\n * @returns 包含日/时/分/秒/毫秒的对象\n */\nexport function parseTimeData(timestamp: number) {\n return {\n days: mathFloor(timestamp / DAY),\n hours: mathFloor((timestamp % DAY) / HOUR),\n minutes: mathFloor((timestamp % HOUR) / MINUTE),\n seconds: mathFloor((timestamp % MINUTE) / SECOND),\n milliseconds: mathFloor(timestamp % SECOND)\n };\n}\n\n/**\n * 格式化时间格式\n *\n * @param format 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒\n * @param timeData 包含日/时/分/秒/毫秒的对象\n * @returns 返回格式化后的时间字符串\n */\nexport function parseFormat(format: string, timeData: ReturnType<typeof parseTimeData>) {\n // eslint-disable-next-line prefer-const\n let { days, hours, minutes, seconds, milliseconds } = timeData;\n\n if (format.indexOf('DD') === -1) {\n hours += days * 24;\n } else {\n format = format.replace('DD', padZero(days));\n }\n\n if (format.indexOf('HH') === -1) {\n minutes += hours * 60;\n } else {\n format = format.replace('HH', padZero(hours));\n }\n\n if (format.indexOf('mm') === -1) {\n seconds += minutes * 60;\n } else {\n format = format.replace('mm', padZero(minutes));\n }\n\n if (format.indexOf('ss') === -1) {\n milliseconds += seconds * 1000;\n } else {\n format = format.replace('ss', padZero(seconds));\n }\n\n return format.replace('SSS', padZero(milliseconds, 3));\n}\n\n/**\n * 格式化时间\n *\n * @param {number} timestamp 时间戳,单位毫秒\n * @param {string} [pattern='HH:mm:ss'] 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒。默认值为 HH:mm:ss\n * @returns {string} 返回格式化后的时间字符串\n */\nexport function format(timestamp: number, pattern = 'HH:mm:ss') {\n const timeData = parseTimeData(timestamp);\n return parseFormat(pattern, timeData);\n}\n\nexport const noop = () => {};\n","import { format, parseTimeData, parseFormat, padZero, noop } from './util';\n\nexport type Options = {\n /**\n * 倒计时,单位毫秒\n */\n time: number;\n\n /**\n * 时间间隔,单位毫秒\n * @default 1000\n */\n interval?: number;\n\n /**\n * 自动校准倒计时时间间隔,单位毫秒。\n *\n * 如果有值且大于 `0`,再开始倒计时时会执行自动校准定时任务。暂定或结束倒计时会停止定时任务。\n */\n adjustInterval?: number;\n\n /**\n * 倒计时时间变动时触发\n * @param {number} currentTime 当前倒计时时间,单位毫秒\n * @returns\n */\n onChange?: (currentTime: number) => void;\n\n /**\n * 倒计时结束时触发\n * @returns\n */\n onEnd?: () => void;\n};\n\nconst defaultInterval = 1000;\n\n/**\n * 倒计时\n *\n * @param {Object} options 配置项\n * @param {number} options.time 倒计时,单位毫秒\n * @param {number} [options.interval=1000] 时间间隔,单位毫秒。默认 `1000`\n * @param {Function} [options.onChange] 倒计时时间变动时触发\n * @param {Function} [options.onEnd] 倒计时结束时触发\n * @param {number} [options.adjustInterval] 自动校准倒计时时间间隔,单位毫秒。如果有值且大于 `0`,再开始倒计时时会执行自动校准定时任务。暂定或结束倒计时会停止定时任务。\n * @returns\n * @example\n * const countdown = new Countdown({\n * time: 60 * 1000\n * interval: 1000,\n * onChange(){},\n * onEnd(){},\n * adjustInterval: 10 * 1000\n * });\n *\n * // 实例方法\n * // 开始倒计时\n * countdown.start();\n *\n * // 暂停倒计时\n * countdown.pause();\n *\n * // 重置倒计时。先暂停再将倒计时时间重置\n * countdown.reset();\n *\n * // 重置再开始倒计时\n * countdown.restart();\n *\n * // 更新配置。如果更新 `time` 需要手动调用 `reset` 或 `restart` 方法才生效\n * countdown.updateOptions(options);\n *\n * // 校准倒计时。在倒计时运行时才生效,如果需要校准会先暂停再开始。\n * countdown.adjustTime();\n *\n * // 静态方法\n * // 格式化时间,返回格式化后的时间字符串\n * CountDown.format(2 * 60 * 60 * 1000); // \"02:00:00\"\n * CountDown.format(2 * 60 * 60 * 1000, 'mm:ss'); // \"120:00\"\n *\n * // 前置补零,返回补零后的值\n * CountDown.padZero(2); // \"02\"\n *\n * // 解析时间戳,返回的时间对象格式\n * CountDown.parseTimeData(2 * 60 * 60 * 1000);\n * // {days: 0, hours: 2, minutes: 0, seconds: 0, milliseconds: 0}\n *\n */\nclass CountDown {\n private o: Required<Options>; // alias\n protected options: Required<Options>;\n\n /**\n * 定时器\n */\n private timer: any;\n\n /**\n * 标识正在倒计时\n */\n private counting: boolean;\n\n /**\n * 标识倒计时完成\n */\n private completed: boolean;\n\n /**\n * 记录当前倒计时长\n */\n private currentTime: number;\n\n /**\n * 记录开始时间戳,用于校准\n */\n private adjustStartTime: number;\n\n /**\n * 记录开始的倒计时长,用于校准\n */\n private adjustCurrentTime: number;\n\n /**\n * 校准倒计时时间定时器\n */\n private adjustTimer: any;\n\n constructor(options: Options) {\n this.options = this.o = {\n onChange: noop,\n onEnd: noop,\n interval: defaultInterval,\n time: 0,\n adjustInterval: 0\n };\n\n this.updateOptions(options);\n\n this.timer = null;\n this.counting = false;\n this.completed = false;\n this.currentTime = this.o.time;\n\n this.adjustStartTime = 0;\n this.adjustCurrentTime = 0;\n this.adjustTimer = null;\n }\n\n private _onEnd() {\n clearInterval(this.adjustTimer);\n this.o.onEnd();\n }\n\n /**\n * 更新配置。\n *\n * 如果更新 `time` 需要手动调用 `reset` 或 `restart` 方法才生效。\n *\n * @param {Object} options 配置项\n * @param {number} [options.time] 倒计时,单位毫秒\n * @param {number} [options.interval] 时间间隔,单位毫秒\n * @param {Function} [options.onChange] 倒计时时间变动时触发\n * @param {Function} [options.onEnd] 倒计时结束时触发\n * @returns\n */\n updateOptions(options: Partial<Options>) {\n if (typeof options === 'object') {\n for (const prop in options) {\n // @ts-ignore\n if (options[prop] !== undefined) {\n // @ts-ignore\n this.o[prop] = options[prop];\n }\n }\n }\n\n // 倒计时长\n if (typeof this.o.time !== 'number' || this.o.time < 0) {\n this.o.time = 0;\n }\n // 倒计时间隔\n if (typeof this.o.interval !== 'number' || this.o.interval < 0) {\n this.o.interval = defaultInterval;\n }\n }\n\n /**\n * 开始倒计时\n * @returns\n */\n start() {\n if (this.counting || this.completed) {\n return;\n }\n\n this.adjustStartTime = Date.now();\n this.adjustCurrentTime = this.currentTime;\n\n if (this.o.adjustInterval > 0) {\n this.adjustTimer = setInterval(() => {\n this.adjustTime();\n }, this.o.adjustInterval);\n }\n\n this.counting = true;\n this.tick();\n }\n\n /**\n * 校准倒计时时间。建议使用 `adjustInterval` 配置。\n *\n * 仅在倒计时运行时才生效。如果需要校准,会先暂停,调用 `onChange` ,再开始倒计时。\n *\n * @example\n * const interval = 1000;\n * let timer = null;\n * const countdown = new CountDown({\n * time: 60 * 1000,\n * interval,\n * onEnd(){\n * clearInterval(timer);\n * }\n * });\n *\n * // 每倒计时10次,校准一次倒计时时间\n * const timer = setInterval(()=>{\n * countdown.adjustTime();\n * }, interval * 10);\n *\n */\n adjustTime() {\n if (this.counting) {\n const currentTimestamp = Date.now();\n const diffTime = currentTimestamp - this.adjustStartTime;\n const diffTimeInt = Math.round(diffTime / this.o.interval) * this.o.interval;\n const newCurrentTime = this.adjustCurrentTime - diffTimeInt;\n if (newCurrentTime >= 0 && this.currentTime !== newCurrentTime) {\n this.pause();\n this.currentTime = newCurrentTime;\n this.o.onChange(this.currentTime);\n this.start();\n }\n }\n }\n\n /**\n * 暂停倒计时\n */\n pause() {\n if (this.counting) {\n clearTimeout(this.timer);\n clearInterval(this.adjustTimer);\n this.counting = false;\n }\n }\n\n /**\n * 重置倒计时。\n *\n * 先暂停再将倒计时时间重置。\n */\n reset() {\n this.pause();\n this.completed = false;\n if (this.currentTime !== this.o.time) {\n this.currentTime = this.o.time;\n this.o.onChange(this.currentTime);\n }\n }\n\n /**\n * 重置再开始倒计时\n */\n restart() {\n this.reset();\n this.start();\n }\n\n private tick() {\n const interval = this.o.interval;\n\n this.timer = setTimeout(() => {\n this.currentTime -= interval;\n\n if (this.currentTime < 0) {\n this.currentTime = 0;\n }\n\n this.o.onChange(this.currentTime);\n\n if (this.currentTime === 0) {\n this.counting = false;\n this.completed = true;\n this._onEnd();\n } else {\n this.tick();\n }\n }, interval);\n }\n\n static format = format;\n static parseTimeData = parseTimeData;\n static parseFormat = parseFormat;\n static padZero = padZero;\n}\n\nexport default CountDown;\n"],"names":[],"mappings":"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"} |
@@ -1,2 +0,2 @@ | ||
| !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).CountDown=e()}(this,(function(){"use strict";function t(t,e){void 0===e&&(e=2);for(var i=""+t;i.length<e;)i="0"+i;return i}var e=1e3,i=60*e,n=60*i,o=24*n,r=Math.floor;function s(t){return{days:r(t/o),hours:r(t%o/n),minutes:r(t%n/i),seconds:r(t%i/e),milliseconds:r(t%e)}}function u(e,i){var n=i.days,o=i.hours,r=i.minutes,s=i.seconds,u=i.milliseconds;return-1===e.indexOf("DD")?o+=24*n:e=e.replace("DD",t(n)),-1===e.indexOf("HH")?r+=60*o:e=e.replace("HH",t(o)),-1===e.indexOf("mm")?s+=60*r:e=e.replace("mm",t(r)),-1===e.indexOf("ss")?u+=1e3*s:e=e.replace("ss",t(s)),e.replace("SSS",t(u,3))}function c(t,e){return void 0===e&&(e="HH:mm:ss"),u(e,s(t))}var h=function(){};return function(){function e(t){this.options=this.o={onChange:h,onEnd:h,interval:1e3,time:0},this.updateOptions(t),this.timer=null,this.counting=!1,this.completed=!1,this.currentTime=this.o.time}return e.prototype.updateOptions=function(t){if("object"==typeof t)for(var e in t)void 0!==t[e]&&(this.o[e]=t[e]);("number"!=typeof this.o.time||this.o.time<0)&&(this.o.time=0),("number"!=typeof this.o.interval||this.o.interval<0)&&(this.o.interval=1e3)},e.prototype.start=function(){this.counting||this.completed||(this.counting=!0,this.tick())},e.prototype.pause=function(){this.counting&&(clearTimeout(this.timer),this.counting=!1)},e.prototype.reset=function(){this.pause(),this.completed=!1,this.currentTime!==this.o.time&&(this.currentTime=this.o.time,this.o.onChange(this.currentTime))},e.prototype.restart=function(){this.reset(),this.start()},e.prototype.tick=function(){var t=this,e=this.o.interval;this.timer=setTimeout((function(){t.currentTime-=e,t.currentTime<0&&(t.currentTime=0),t.o.onChange(t.currentTime),0===t.currentTime?(t.counting=!1,t.completed=!0,t.o.onEnd()):t.tick()}),e)},e.format=c,e.parseTimeData=s,e.parseFormat=u,e.padZero=t,e}()})); | ||
| !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).CountDown=e()}(this,(function(){"use strict";function t(t,e){void 0===e&&(e=2);for(var i=""+t;i.length<e;)i="0"+i;return i}var e=1e3,i=60*e,n=60*i,s=24*n,o=Math.floor;function r(t){return{days:o(t/s),hours:o(t%s/n),minutes:o(t%n/i),seconds:o(t%i/e),milliseconds:o(t%e)}}function u(e,i){var n=i.days,s=i.hours,o=i.minutes,r=i.seconds,u=i.milliseconds;return-1===e.indexOf("DD")?s+=24*n:e=e.replace("DD",t(n)),-1===e.indexOf("HH")?o+=60*s:e=e.replace("HH",t(s)),-1===e.indexOf("mm")?r+=60*o:e=e.replace("mm",t(o)),-1===e.indexOf("ss")?u+=1e3*r:e=e.replace("ss",t(r)),e.replace("SSS",t(u,3))}function a(t,e){return void 0===e&&(e="HH:mm:ss"),u(e,r(t))}var h=function(){};return function(){function e(t){this.options=this.o={onChange:h,onEnd:h,interval:1e3,time:0,adjustInterval:0},this.updateOptions(t),this.timer=null,this.counting=!1,this.completed=!1,this.currentTime=this.o.time,this.adjustStartTime=0,this.adjustCurrentTime=0,this.adjustTimer=null}return e.prototype._onEnd=function(){clearInterval(this.adjustTimer),this.o.onEnd()},e.prototype.updateOptions=function(t){if("object"==typeof t)for(var e in t)void 0!==t[e]&&(this.o[e]=t[e]);("number"!=typeof this.o.time||this.o.time<0)&&(this.o.time=0),("number"!=typeof this.o.interval||this.o.interval<0)&&(this.o.interval=1e3)},e.prototype.start=function(){var t=this;this.counting||this.completed||(this.adjustStartTime=Date.now(),this.adjustCurrentTime=this.currentTime,this.o.adjustInterval>0&&(this.adjustTimer=setInterval((function(){t.adjustTime()}),this.o.adjustInterval)),this.counting=!0,this.tick())},e.prototype.adjustTime=function(){if(this.counting){var t=Date.now()-this.adjustStartTime,e=Math.round(t/this.o.interval)*this.o.interval,i=this.adjustCurrentTime-e;i>=0&&this.currentTime!==i&&(this.pause(),this.currentTime=i,this.o.onChange(this.currentTime),this.start())}},e.prototype.pause=function(){this.counting&&(clearTimeout(this.timer),clearInterval(this.adjustTimer),this.counting=!1)},e.prototype.reset=function(){this.pause(),this.completed=!1,this.currentTime!==this.o.time&&(this.currentTime=this.o.time,this.o.onChange(this.currentTime))},e.prototype.restart=function(){this.reset(),this.start()},e.prototype.tick=function(){var t=this,e=this.o.interval;this.timer=setTimeout((function(){t.currentTime-=e,t.currentTime<0&&(t.currentTime=0),t.o.onChange(t.currentTime),0===t.currentTime?(t.counting=!1,t.completed=!0,t._onEnd()):t.tick()}),e)},e.format=a,e.parseTimeData=r,e.parseFormat=u,e.padZero=t,e}()})); | ||
| //# sourceMappingURL=countdown.umd.min.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"countdown.umd.min.js","sources":["../src/util.ts","../src/countdown.ts"],"sourcesContent":["/**\n * 前置补零,如果值的长度小于目标长度,则前置补零,否则不处理\n *\n * @param num 待处理的值\n * @param targetLength 目标长度\n * @returns 补零后的值\n */\nexport function padZero(num: string | number, targetLength = 2) {\n let str = '' + num;\n while (str.length < targetLength) {\n str = '0' + str;\n }\n return str;\n}\n\nconst SECOND = 1000;\nconst MINUTE = 60 * SECOND;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\n\nconst mathFloor = Math.floor;\n\n/**\n * 解析时间戳\n *\n * @param {number} timestamp 时间戳,单位毫秒\n * @returns 包含日/时/分/秒/毫秒的对象\n */\nexport function parseTimeData(timestamp: number) {\n return {\n days: mathFloor(timestamp / DAY),\n hours: mathFloor((timestamp % DAY) / HOUR),\n minutes: mathFloor((timestamp % HOUR) / MINUTE),\n seconds: mathFloor((timestamp % MINUTE) / SECOND),\n milliseconds: mathFloor(timestamp % SECOND)\n };\n}\n\n/**\n * 格式化时间格式\n *\n * @param format 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒\n * @param timeData 包含日/时/分/秒/毫秒的对象\n * @returns 返回格式化后的时间字符串\n */\nexport function parseFormat(format: string, timeData: ReturnType<typeof parseTimeData>) {\n // eslint-disable-next-line prefer-const\n let { days, hours, minutes, seconds, milliseconds } = timeData;\n\n if (format.indexOf('DD') === -1) {\n hours += days * 24;\n } else {\n format = format.replace('DD', padZero(days));\n }\n\n if (format.indexOf('HH') === -1) {\n minutes += hours * 60;\n } else {\n format = format.replace('HH', padZero(hours));\n }\n\n if (format.indexOf('mm') === -1) {\n seconds += minutes * 60;\n } else {\n format = format.replace('mm', padZero(minutes));\n }\n\n if (format.indexOf('ss') === -1) {\n milliseconds += seconds * 1000;\n } else {\n format = format.replace('ss', padZero(seconds));\n }\n\n return format.replace('SSS', padZero(milliseconds, 3));\n}\n\n/**\n * 格式化时间\n *\n * @param {number} timestamp 时间戳,单位毫秒\n * @param {string} [pattern='HH:mm:ss'] 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒。默认值为 HH:mm:ss\n * @returns {string} 返回格式化后的时间字符串\n */\nexport function format(timestamp: number, pattern = 'HH:mm:ss') {\n const timeData = parseTimeData(timestamp);\n return parseFormat(pattern, timeData);\n}\n\nexport const noop = () => {};\n","import { format, parseTimeData, parseFormat, padZero, noop } from './util';\n\nexport type Options = {\n time: number;\n interval?: number;\n onChange?: (currentTime: number) => void;\n onEnd?: () => void;\n};\n\nconst defaultInterval = 1000;\n\nclass CountDown {\n private o: Required<Options>; // alias\n protected options: Required<Options>;\n\n private timer: any;\n private counting: boolean;\n private completed: boolean;\n private currentTime: number;\n\n constructor(options: Options) {\n this.options = this.o = {\n onChange: noop,\n onEnd: noop,\n interval: defaultInterval,\n time: 0\n };\n\n this.updateOptions(options);\n\n this.timer = null; // 定时器\n this.counting = false; // 标识正在倒计时\n this.completed = false; // 标识倒计时完成\n this.currentTime = this.o.time; // 记录当前倒计时长\n }\n\n updateOptions(options: Partial<Options>) {\n if (typeof options === 'object') {\n for (const prop in options) {\n // @ts-ignore\n if (options[prop] !== undefined) {\n // @ts-ignore\n this.o[prop] = options[prop];\n }\n }\n }\n\n // 倒计时长\n if (typeof this.o.time !== 'number' || this.o.time < 0) {\n this.o.time = 0;\n }\n // 倒计时间隔\n if (typeof this.o.interval !== 'number' || this.o.interval < 0) {\n this.o.interval = defaultInterval;\n }\n }\n\n // 开始\n start() {\n if (this.counting || this.completed) {\n return;\n }\n\n this.counting = true;\n this.tick();\n }\n\n // 暂停\n pause() {\n if (this.counting) {\n clearTimeout(this.timer);\n this.counting = false;\n }\n }\n\n // 重置\n reset() {\n this.pause();\n this.completed = false;\n if (this.currentTime !== this.o.time) {\n this.currentTime = this.o.time;\n this.o.onChange(this.currentTime);\n }\n }\n\n // 重新开始\n restart() {\n this.reset();\n this.start();\n }\n\n private tick() {\n const interval = this.o.interval;\n\n this.timer = setTimeout(() => {\n this.currentTime -= interval;\n\n if (this.currentTime < 0) {\n this.currentTime = 0;\n }\n\n this.o.onChange(this.currentTime);\n\n if (this.currentTime === 0) {\n this.counting = false;\n this.completed = true;\n this.o.onEnd();\n } else {\n this.tick();\n }\n }, interval);\n }\n\n static format = format;\n static parseTimeData = parseTimeData;\n static parseFormat = parseFormat;\n static padZero = padZero;\n}\n\nexport default CountDown;\n"],"names":["padZero","num","targetLength","str","length","SECOND","MINUTE","HOUR","DAY","mathFloor","Math","floor","parseTimeData","timestamp","days","hours","minutes","seconds","milliseconds","parseFormat","format","timeData","indexOf","replace","pattern","noop","CountDown","options","this","o","onChange","onEnd","interval","time","updateOptions","timer","counting","completed","currentTime","prototype","prop","undefined","start","tick","pause","clearTimeout","reset","restart","_this","setTimeout"],"mappings":"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"} | ||
| {"version":3,"file":"countdown.umd.min.js","sources":["../src/util.ts","../src/countdown.ts"],"sourcesContent":["/**\n * 前置补零,如果值的长度小于目标长度,则前置补零,否则不处理\n *\n * @param num 待处理的值\n * @param targetLength 目标长度\n * @returns 补零后的值\n */\nexport function padZero(num: string | number, targetLength = 2) {\n let str = '' + num;\n while (str.length < targetLength) {\n str = '0' + str;\n }\n return str;\n}\n\nconst SECOND = 1000;\nconst MINUTE = 60 * SECOND;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\n\nconst mathFloor = Math.floor;\n\n/**\n * 解析时间戳\n *\n * @param {number} timestamp 时间戳,单位毫秒\n * @returns 包含日/时/分/秒/毫秒的对象\n */\nexport function parseTimeData(timestamp: number) {\n return {\n days: mathFloor(timestamp / DAY),\n hours: mathFloor((timestamp % DAY) / HOUR),\n minutes: mathFloor((timestamp % HOUR) / MINUTE),\n seconds: mathFloor((timestamp % MINUTE) / SECOND),\n milliseconds: mathFloor(timestamp % SECOND)\n };\n}\n\n/**\n * 格式化时间格式\n *\n * @param format 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒\n * @param timeData 包含日/时/分/秒/毫秒的对象\n * @returns 返回格式化后的时间字符串\n */\nexport function parseFormat(format: string, timeData: ReturnType<typeof parseTimeData>) {\n // eslint-disable-next-line prefer-const\n let { days, hours, minutes, seconds, milliseconds } = timeData;\n\n if (format.indexOf('DD') === -1) {\n hours += days * 24;\n } else {\n format = format.replace('DD', padZero(days));\n }\n\n if (format.indexOf('HH') === -1) {\n minutes += hours * 60;\n } else {\n format = format.replace('HH', padZero(hours));\n }\n\n if (format.indexOf('mm') === -1) {\n seconds += minutes * 60;\n } else {\n format = format.replace('mm', padZero(minutes));\n }\n\n if (format.indexOf('ss') === -1) {\n milliseconds += seconds * 1000;\n } else {\n format = format.replace('ss', padZero(seconds));\n }\n\n return format.replace('SSS', padZero(milliseconds, 3));\n}\n\n/**\n * 格式化时间\n *\n * @param {number} timestamp 时间戳,单位毫秒\n * @param {string} [pattern='HH:mm:ss'] 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒。默认值为 HH:mm:ss\n * @returns {string} 返回格式化后的时间字符串\n */\nexport function format(timestamp: number, pattern = 'HH:mm:ss') {\n const timeData = parseTimeData(timestamp);\n return parseFormat(pattern, timeData);\n}\n\nexport const noop = () => {};\n","import { format, parseTimeData, parseFormat, padZero, noop } from './util';\n\nexport type Options = {\n /**\n * 倒计时,单位毫秒\n */\n time: number;\n\n /**\n * 时间间隔,单位毫秒\n * @default 1000\n */\n interval?: number;\n\n /**\n * 自动校准倒计时时间间隔,单位毫秒。\n *\n * 如果有值且大于 `0`,再开始倒计时时会执行自动校准定时任务。暂定或结束倒计时会停止定时任务。\n */\n adjustInterval?: number;\n\n /**\n * 倒计时时间变动时触发\n * @param {number} currentTime 当前倒计时时间,单位毫秒\n * @returns\n */\n onChange?: (currentTime: number) => void;\n\n /**\n * 倒计时结束时触发\n * @returns\n */\n onEnd?: () => void;\n};\n\nconst defaultInterval = 1000;\n\n/**\n * 倒计时\n *\n * @param {Object} options 配置项\n * @param {number} options.time 倒计时,单位毫秒\n * @param {number} [options.interval=1000] 时间间隔,单位毫秒。默认 `1000`\n * @param {Function} [options.onChange] 倒计时时间变动时触发\n * @param {Function} [options.onEnd] 倒计时结束时触发\n * @param {number} [options.adjustInterval] 自动校准倒计时时间间隔,单位毫秒。如果有值且大于 `0`,再开始倒计时时会执行自动校准定时任务。暂定或结束倒计时会停止定时任务。\n * @returns\n * @example\n * const countdown = new Countdown({\n * time: 60 * 1000\n * interval: 1000,\n * onChange(){},\n * onEnd(){},\n * adjustInterval: 10 * 1000\n * });\n *\n * // 实例方法\n * // 开始倒计时\n * countdown.start();\n *\n * // 暂停倒计时\n * countdown.pause();\n *\n * // 重置倒计时。先暂停再将倒计时时间重置\n * countdown.reset();\n *\n * // 重置再开始倒计时\n * countdown.restart();\n *\n * // 更新配置。如果更新 `time` 需要手动调用 `reset` 或 `restart` 方法才生效\n * countdown.updateOptions(options);\n *\n * // 校准倒计时。在倒计时运行时才生效,如果需要校准会先暂停再开始。\n * countdown.adjustTime();\n *\n * // 静态方法\n * // 格式化时间,返回格式化后的时间字符串\n * CountDown.format(2 * 60 * 60 * 1000); // \"02:00:00\"\n * CountDown.format(2 * 60 * 60 * 1000, 'mm:ss'); // \"120:00\"\n *\n * // 前置补零,返回补零后的值\n * CountDown.padZero(2); // \"02\"\n *\n * // 解析时间戳,返回的时间对象格式\n * CountDown.parseTimeData(2 * 60 * 60 * 1000);\n * // {days: 0, hours: 2, minutes: 0, seconds: 0, milliseconds: 0}\n *\n */\nclass CountDown {\n private o: Required<Options>; // alias\n protected options: Required<Options>;\n\n /**\n * 定时器\n */\n private timer: any;\n\n /**\n * 标识正在倒计时\n */\n private counting: boolean;\n\n /**\n * 标识倒计时完成\n */\n private completed: boolean;\n\n /**\n * 记录当前倒计时长\n */\n private currentTime: number;\n\n /**\n * 记录开始时间戳,用于校准\n */\n private adjustStartTime: number;\n\n /**\n * 记录开始的倒计时长,用于校准\n */\n private adjustCurrentTime: number;\n\n /**\n * 校准倒计时时间定时器\n */\n private adjustTimer: any;\n\n constructor(options: Options) {\n this.options = this.o = {\n onChange: noop,\n onEnd: noop,\n interval: defaultInterval,\n time: 0,\n adjustInterval: 0\n };\n\n this.updateOptions(options);\n\n this.timer = null;\n this.counting = false;\n this.completed = false;\n this.currentTime = this.o.time;\n\n this.adjustStartTime = 0;\n this.adjustCurrentTime = 0;\n this.adjustTimer = null;\n }\n\n private _onEnd() {\n clearInterval(this.adjustTimer);\n this.o.onEnd();\n }\n\n /**\n * 更新配置。\n *\n * 如果更新 `time` 需要手动调用 `reset` 或 `restart` 方法才生效。\n *\n * @param {Object} options 配置项\n * @param {number} [options.time] 倒计时,单位毫秒\n * @param {number} [options.interval] 时间间隔,单位毫秒\n * @param {Function} [options.onChange] 倒计时时间变动时触发\n * @param {Function} [options.onEnd] 倒计时结束时触发\n * @returns\n */\n updateOptions(options: Partial<Options>) {\n if (typeof options === 'object') {\n for (const prop in options) {\n // @ts-ignore\n if (options[prop] !== undefined) {\n // @ts-ignore\n this.o[prop] = options[prop];\n }\n }\n }\n\n // 倒计时长\n if (typeof this.o.time !== 'number' || this.o.time < 0) {\n this.o.time = 0;\n }\n // 倒计时间隔\n if (typeof this.o.interval !== 'number' || this.o.interval < 0) {\n this.o.interval = defaultInterval;\n }\n }\n\n /**\n * 开始倒计时\n * @returns\n */\n start() {\n if (this.counting || this.completed) {\n return;\n }\n\n this.adjustStartTime = Date.now();\n this.adjustCurrentTime = this.currentTime;\n\n if (this.o.adjustInterval > 0) {\n this.adjustTimer = setInterval(() => {\n this.adjustTime();\n }, this.o.adjustInterval);\n }\n\n this.counting = true;\n this.tick();\n }\n\n /**\n * 校准倒计时时间。建议使用 `adjustInterval` 配置。\n *\n * 仅在倒计时运行时才生效。如果需要校准,会先暂停,调用 `onChange` ,再开始倒计时。\n *\n * @example\n * const interval = 1000;\n * let timer = null;\n * const countdown = new CountDown({\n * time: 60 * 1000,\n * interval,\n * onEnd(){\n * clearInterval(timer);\n * }\n * });\n *\n * // 每倒计时10次,校准一次倒计时时间\n * const timer = setInterval(()=>{\n * countdown.adjustTime();\n * }, interval * 10);\n *\n */\n adjustTime() {\n if (this.counting) {\n const currentTimestamp = Date.now();\n const diffTime = currentTimestamp - this.adjustStartTime;\n const diffTimeInt = Math.round(diffTime / this.o.interval) * this.o.interval;\n const newCurrentTime = this.adjustCurrentTime - diffTimeInt;\n if (newCurrentTime >= 0 && this.currentTime !== newCurrentTime) {\n this.pause();\n this.currentTime = newCurrentTime;\n this.o.onChange(this.currentTime);\n this.start();\n }\n }\n }\n\n /**\n * 暂停倒计时\n */\n pause() {\n if (this.counting) {\n clearTimeout(this.timer);\n clearInterval(this.adjustTimer);\n this.counting = false;\n }\n }\n\n /**\n * 重置倒计时。\n *\n * 先暂停再将倒计时时间重置。\n */\n reset() {\n this.pause();\n this.completed = false;\n if (this.currentTime !== this.o.time) {\n this.currentTime = this.o.time;\n this.o.onChange(this.currentTime);\n }\n }\n\n /**\n * 重置再开始倒计时\n */\n restart() {\n this.reset();\n this.start();\n }\n\n private tick() {\n const interval = this.o.interval;\n\n this.timer = setTimeout(() => {\n this.currentTime -= interval;\n\n if (this.currentTime < 0) {\n this.currentTime = 0;\n }\n\n this.o.onChange(this.currentTime);\n\n if (this.currentTime === 0) {\n this.counting = false;\n this.completed = true;\n this._onEnd();\n } else {\n this.tick();\n }\n }, interval);\n }\n\n static format = format;\n static parseTimeData = parseTimeData;\n static parseFormat = parseFormat;\n static padZero = padZero;\n}\n\nexport default CountDown;\n"],"names":["padZero","num","targetLength","str","length","SECOND","MINUTE","HOUR","DAY","mathFloor","Math","floor","parseTimeData","timestamp","days","hours","minutes","seconds","milliseconds","parseFormat","format","timeData","indexOf","replace","pattern","noop","CountDown","options","this","o","onChange","onEnd","interval","time","adjustInterval","updateOptions","timer","counting","completed","currentTime","adjustStartTime","adjustCurrentTime","adjustTimer","prototype","_onEnd","clearInterval","prop","undefined","start","_this","Date","now","setInterval","adjustTime","tick","diffTime","diffTimeInt","round","newCurrentTime","pause","clearTimeout","reset","restart","setTimeout"],"mappings":"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"} |
+1
-1
| { | ||
| "name": "countdown-pro", | ||
| "version": "2.1.0", | ||
| "version": "2.2.0", | ||
| "description": "A simple countdown.", | ||
@@ -5,0 +5,0 @@ "main": "dist/countdown.cjs.js", |
+55
-16
@@ -11,3 +11,3 @@ # CountDown | ||
| **安装** | ||
| ### 安装 | ||
@@ -26,3 +26,3 @@ ```shell | ||
| **浏览器引入** | ||
| ### 浏览器引入 | ||
@@ -56,17 +56,20 @@ 在浏览器中使用 `script` 标签直接引入文件,并使用全局变量 `CountDown` 。 | ||
| | 参数 | 说明 | 类型 | 必填 | 默认值 | | ||
| | -------- | ------------------ | ----------------------- | ---- | ------ | | ||
| | time | 倒计时,单位毫秒 | `number` | `Y` | `0` | | ||
| | interval | 时间间隔,单位毫秒 | `number` | - | `1000` | | ||
| | onChange | 每次时间间隔时触发 | `(currentTime) => void` | - | - | | ||
| | onEnd | 倒计时结束时触发 | `() => void` | - | - | | ||
| | 参数 | 说明 | 类型 | 必填 | 默认值 | | ||
| | --- | --- | --- | --- | --- | | ||
| | time | 倒计时,单位毫秒 | `number` | `Y` | `0` | | ||
| | interval | 时间间隔,单位毫秒 | `number` | `N` | `1000` | | ||
| | onChange | 倒计时时间变动时触发 | `(currentTime: number) => void` | `N` | - | | ||
| | onEnd | 倒计时结束时触发 | `() => void` | `N` | - | | ||
| | adjustInterval | 自动校准倒计时时间间隔,单位毫秒。<br/>如果有值且大于 `0`,再开始倒计时时会执行自动校准定时任务。暂定或结束倒计时会停止定时任务。 | `number` | `N` | - | | ||
| ## 实例方法 | ||
| | 方法名 | 说明 | | ||
| | ------- | ---------------- | | ||
| | start | 开始倒计时 | | ||
| | pause | 暂停倒计时 | | ||
| | reset | 重置倒计时 | | ||
| | restart | 重置再开始倒计时 | | ||
| | 方法名 | 说明 | | ||
| | ------------- | ----------------------------------------------------------------------------- | | ||
| | start | 开始倒计时 | | ||
| | pause | 暂停倒计时 | | ||
| | reset | 重置倒计时。先暂停再将倒计时时间重置。 | | ||
| | restart | 重置再开始倒计时 | | ||
| | updateOptions | 更新配置。<br/>如果更新 `time` 需要手动调用 `reset` 或 `restart` 方法才生效。 | | ||
| | adjustTime | 校准倒计时。<br/>仅在倒计时运行时才生效,如果需要校准会先暂停再开始。 | | ||
@@ -104,3 +107,3 @@ ## 静态方法 | ||
| ```typescript | ||
| interface TimeData { | ||
| type TimeData = { | ||
| days: number; // 天数 | ||
@@ -111,3 +114,3 @@ hours: number; // 小时 | ||
| milliseconds: number; // 毫秒 | ||
| } | ||
| }; | ||
| ``` | ||
@@ -119,4 +122,40 @@ | ||
| ## 常见问题 | ||
| ### 如何解决误差? | ||
| > 参考:[延时比指定值更长的原因](https://developer.mozilla.org/zh-CN/docs/Web/API/setTimeout#%E5%BB%B6%E6%97%B6%E6%AF%94%E6%8C%87%E5%AE%9A%E5%80%BC%E6%9B%B4%E9%95%BF%E7%9A%84%E5%8E%9F%E5%9B%A0) | ||
| 如果是应用于弱时效性的场景,可以忽略延时误差。如短信验证码重新发送倒计时。 | ||
| 如果是秒杀、抢购等强时效性的场景,通过服务器时间校对比较靠谱。可以监听页面可见或隐藏事件、固定间隔时间等方式获取最新的服务器时间,然后更新倒计时。 | ||
| ```typescript | ||
| const countdown = new Countdown({ | ||
| // ... | ||
| }); | ||
| document.addEventListener('visibilityChange', function () { | ||
| if (!document.hidden) { | ||
| // 获取服务器时间 | ||
| // ... | ||
| countdown.updateOptions({ | ||
| time: finalTime - serviceTime | ||
| }); | ||
| countdown.restart(); | ||
| } | ||
| }); | ||
| setInterval(() => { | ||
| // 获取服务器时间 | ||
| // ... | ||
| countdown.updateOptions({ | ||
| time: finalTime - serviceTime | ||
| }); | ||
| countdown.restart(); | ||
| }, 60 * 1000); | ||
| ``` | ||
| [site]: https://caijf.github.io/countdown/examples/ | ||
| [npm]: https://img.shields.io/npm/v/countdown-pro.svg | ||
| [npm-url]: https://npmjs.com/package/countdown-pro |
+148
-0
| import { format, parseTimeData, parseFormat, padZero } from './util'; | ||
| export type Options = { | ||
| /** | ||
| * 倒计时,单位毫秒 | ||
| */ | ||
| time: number; | ||
| /** | ||
| * 时间间隔,单位毫秒 | ||
| * @default 1000 | ||
| */ | ||
| interval?: number; | ||
| /** | ||
| * 自动校准倒计时时间间隔,单位毫秒。 | ||
| * | ||
| * 如果有值且大于 `0`,再开始倒计时时会执行自动校准定时任务。暂定或结束倒计时会停止定时任务。 | ||
| */ | ||
| adjustInterval?: number; | ||
| /** | ||
| * 倒计时时间变动时触发 | ||
| * @param {number} currentTime 当前倒计时时间,单位毫秒 | ||
| * @returns | ||
| */ | ||
| onChange?: (currentTime: number) => void; | ||
| /** | ||
| * 倒计时结束时触发 | ||
| * @returns | ||
| */ | ||
| onEnd?: () => void; | ||
| }; | ||
| /** | ||
| * 倒计时 | ||
| * | ||
| * @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} | ||
| * | ||
| */ | ||
| declare class CountDown { | ||
| private o; | ||
| protected options: Required<Options>; | ||
| /** | ||
| * 定时器 | ||
| */ | ||
| private timer; | ||
| /** | ||
| * 标识正在倒计时 | ||
| */ | ||
| private counting; | ||
| /** | ||
| * 标识倒计时完成 | ||
| */ | ||
| private completed; | ||
| /** | ||
| * 记录当前倒计时长 | ||
| */ | ||
| private currentTime; | ||
| /** | ||
| * 记录开始时间戳,用于校准 | ||
| */ | ||
| private adjustStartTime; | ||
| /** | ||
| * 记录开始的倒计时长,用于校准 | ||
| */ | ||
| private adjustCurrentTime; | ||
| /** | ||
| * 校准倒计时时间定时器 | ||
| */ | ||
| private adjustTimer; | ||
| constructor(options: Options); | ||
| private _onEnd; | ||
| /** | ||
| * 更新配置。 | ||
| * | ||
| * 如果更新 `time` 需要手动调用 `reset` 或 `restart` 方法才生效。 | ||
| * | ||
| * @param {Object} options 配置项 | ||
| * @param {number} [options.time] 倒计时,单位毫秒 | ||
| * @param {number} [options.interval] 时间间隔,单位毫秒 | ||
| * @param {Function} [options.onChange] 倒计时时间变动时触发 | ||
| * @param {Function} [options.onEnd] 倒计时结束时触发 | ||
| * @returns | ||
| */ | ||
| updateOptions(options: Partial<Options>): void; | ||
| /** | ||
| * 开始倒计时 | ||
| * @returns | ||
| */ | ||
| start(): void; | ||
| /** | ||
| * 校准倒计时时间。建议使用 `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); | ||
| * | ||
| */ | ||
| adjustTime(): void; | ||
| /** | ||
| * 暂停倒计时 | ||
| */ | ||
| pause(): void; | ||
| /** | ||
| * 重置倒计时。 | ||
| * | ||
| * 先暂停再将倒计时时间重置。 | ||
| */ | ||
| reset(): void; | ||
| /** | ||
| * 重置再开始倒计时 | ||
| */ | ||
| restart(): void; | ||
@@ -21,0 +169,0 @@ private tick; |
77398
69.01%1133
88.52%156
33.33%