Skip to content

Commit

Permalink
fix: accurate-timer
Browse files Browse the repository at this point in the history
  • Loading branch information
Innei authored and kagol committed Jun 29, 2022
1 parent 867a25b commit f3950dc
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 21 deletions.
13 changes: 7 additions & 6 deletions packages/devui-vue/devui/countdown/src/countdown.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { defineComponent, ref, onUnmounted, onMounted } from 'vue';
import { countdownProps, CountdownProps } from './countdown-types';
import { getFormatTime, getLegalTime, getTimeSplit, getDeduplication, numFormat } from './utils';
import { getFormatTime, getLegalTime, getTimeSplit, getDeduplication, numFormat, intervalTimer } from './utils';
import './countdown.scss';

export default defineComponent({
name: 'DCountdown',
props: countdownProps,
emits: ['onChange', 'onFinish'],
setup(props: CountdownProps, ctx) {
const countdown = ref<number>();
const timerCleaner = ref<(() => void) | undefined | null>();
const s = getDeduplication(props.format);
const timeFormat = getTimeSplit(props.format);
const timeStr = ref('');
Expand Down Expand Up @@ -40,15 +40,16 @@ export default defineComponent({

const startTime = () => {
getTime();
if (countdown.value) {
if (timerCleaner.value) {
return;
}
countdown.value = setInterval(
timerCleaner.value = intervalTimer(
() => {
const t = getTime();
if (t === 0) {
ctx.emit('onFinish');
clearInterval(countdown.value);
timerCleaner.value?.();
timerCleaner.value = null;
}
},
s.has('S') ? 100 : 1000
Expand All @@ -59,7 +60,7 @@ export default defineComponent({
startTime();
});
onUnmounted(() => {
clearInterval(countdown.value);
timerCleaner.value?.();
});
return () => {
return (
Expand Down
63 changes: 53 additions & 10 deletions packages/devui-vue/devui/countdown/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@

export const getFormatTime = (leftTime: number): Map<string, number> => {
const timeformat = new Map([['Y', 0], ['M', 0], ['D', 0], ['H', 0], ['m', 0], ['s', 0], ['S', 0]]);
const timeformat = new Map([
['Y', 0],
['M', 0],
['D', 0],
['H', 0],
['m', 0],
['s', 0],
['S', 0],
]);
const year = Math.floor(leftTime / (365 * 24 * 60 * 60 * 1000));
const month = Math.floor(leftTime / (30 * 24 * 60 * 60 * 1000) % 12);
const day = Math.floor(leftTime / (24 * 60 * 60 * 1000) % 30);
const hour = Math.floor(leftTime / (60 * 60 * 1000) % 24);
const minute = Math.floor(leftTime / (60 * 1000) % 60);
const second = Math.floor(leftTime / 1000 % 60);
const month = Math.floor((leftTime / (30 * 24 * 60 * 60 * 1000)) % 12);
const day = Math.floor((leftTime / (24 * 60 * 60 * 1000)) % 30);
const hour = Math.floor((leftTime / (60 * 60 * 1000)) % 24);
const minute = Math.floor((leftTime / (60 * 1000)) % 60);
const second = Math.floor((leftTime / 1000) % 60);
const millsecond = leftTime % 1000;
timeformat.set('Y', year);
timeformat.set('M', month);
Expand All @@ -19,8 +26,24 @@ export const getFormatTime = (leftTime: number): Map<string, number> => {
};

export const getLegalTime = (s: Set<string>, timeformat: Map<string, number>): Map<string, number> => {
const dateValue = new Map([['Y', 0], ['M', 0], ['D', 0], ['H', 0], ['m', 0], ['s', 0], ['S', 0]]);
const m = new Map([['Y', 12], ['M', 30], ['D', 24], ['H', 60], ['m', 60], ['s', 1000], ['S', 1]]);
const dateValue = new Map([
['Y', 0],
['M', 0],
['D', 0],
['H', 0],
['m', 0],
['s', 0],
['S', 0],
]);
const m = new Map([
['Y', 12],
['M', 30],
['D', 24],
['H', 60],
['m', 60],
['s', 1000],
['S', 1],
]);
let storage = 0;
for (const k of dateValue.keys()) {
if (s.has(k)) {
Expand All @@ -36,7 +59,6 @@ export const getLegalTime = (s: Set<string>, timeformat: Map<string, number>): M
return dateValue;
};


interface ITimeSplit {
k: string;
n: number;
Expand Down Expand Up @@ -79,3 +101,24 @@ export const numFormat = (n: number, len: number): number | string => {
return str + n;
}
};

export const intervalTimer = (callback: (...args: any[]) => any, interval = 0) => {
let counter = 1;
let timeoutId: any;
const startTime = Date.now();

function main() {
const nowTime = Date.now();
const nextTime = startTime + counter * interval;
timeoutId = setTimeout(main, interval - (nowTime - nextTime));

counter += 1;
callback();
}

timeoutId = setTimeout(main, interval);

return () => {
clearTimeout(timeoutId);
};
};
10 changes: 5 additions & 5 deletions packages/devui-vue/docs/components/countdown/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { defineComponent, ref } from 'vue'
export default defineComponent({
setup() {
const deadline = ref(Date.now() + 100 *1000);
const deadline = ref(Date.now() + 100 * 1000);
const changeTime = (n) => {
}
const finishTime = () => {
Expand Down Expand Up @@ -61,7 +61,7 @@ import { defineComponent, ref } from 'vue'
export default defineComponent({
setup() {
const deadline = ref(Date.now() + 2 * 60 * 60 *1000);
const deadline = ref(Date.now() + 2 * 60 * 60 * 1000);
const changeTime = (n) => {
}
const finishTime = () => {
Expand Down Expand Up @@ -99,7 +99,7 @@ import { defineComponent, ref } from 'vue'
export default defineComponent({
setup() {
const deadline = ref(new Date().getTime() + 369 * 24 * 60 * 60 *1000 + 5000);
const deadline = ref(new Date().getTime() + 369 * 24 * 60 * 60 * 1000 + 5000);
const changeTime = (n) => {
}
Expand All @@ -123,8 +123,8 @@ export default defineComponent({



注:当format某一项时间没有的情况下,会将没有的那一项值累积到下一项。
例如:当没有M(月)的时候,会将月的值*30累加到日,根据format格式化的值会从通过时间onchange的legalTime值返回,如下:
注:当 format 某一项时间没有的情况下,会将没有的那一项值累积到下一项。
例如:当没有 M(月)的时候,会将月的值 *30 累加到日,根据 format 格式化的值会从通过时间 onchange 的 legalTime 值返回,如下:
:::demo

```vue
Expand Down

0 comments on commit f3950dc

Please sign in to comment.