@cataract6545/tmui
Version:
tm-vuetify是一个新势力由主题驱动的UI组件库,相比其它优势大,组件全,设计趋势紧跟未来。具有主题生成,主题实时切换,暗黑实时切换,lottie动画,图表等新颖功能,tmui TMUI
207 lines (190 loc) • 5.36 kB
text/typescript
//倒计时
import { ref, computed, ComputedRef, watch } from 'vue';
interface TimerOptions {
totalTime : number; // 总时间,单位毫秒
unit ?: 'ms' | 'ss' | 'mm' | 'hh' | 'dd'; // 时间单位,默认为毫秒
format ?: string; // 时间格式,例如 'yy年dd天 hh时mm分ss秒ms毫秒'
}
interface FormattedTime {
year : number;
day : number;
hour : number;
minute : number;
second : number;
millisecond : number;
}
interface TimerState {
times : ComputedRef<number>;
formattedTime : ComputedRef<(format ?: string) => string>;
timeObj : ComputedRef<FormattedTime>; // 新增 timeObj 属性
/**0暂停中,1,运行中,-1从未开始运行过 */
status : ComputedRef<0 | 1 | -1>;
start : () => void;
stop : () => void;
restart : () => void;
beforeStart : (call : () => void) => void;
timeEnd : (call : () => void) => void;
change : (call : (n : number) => void) => void;
}
/**
* 倒计时
* @description 方便计时操作。
*/
export function useTimer(options : TimerOptions) : TimerState {
const { totalTime, unit = 'ms', format = '' } = options;
const times = ref(calculateRemainingTime());
const status = ref<-1 | 0 | 1>(-1); // 'not_started', 'running', 'paused'
let _beforeStart = () => { };
let _timeEnd = () => { };
let _change = (n : number) => { };
let timerInterval = 50; // 定时器间隔,单位毫秒
if (unit != 'ms') {
timerInterval = 1000
}
let timer : NodeJS.Timeout | null = null;
let animationFrameId : number | null = null; // 用于存储 requestAnimationFrame 的 ID
const timeFomartValue = computed(() => {
switch (unit) {
case 'ms':
return times.value;
case 'ss':
return Math.floor(times.value / 1000);
case 'mm':
return Math.floor(times.value / 60000);
case 'hh':
return Math.floor(times.value / 3600000);
case 'dd':
return Math.floor(times.value / 86400000);
default:
return times.value;
}
})
// #ifndef H5
const start = () => {
if (status.value === -1 || status.value === 0) {
status.value = 1;
_beforeStart();
timer = setInterval(() => {
times.value -= timerInterval;
if (times.value >= 0) {
_change(timeFomartValue.value)
}
if (times.value <= 0) {
times.value = 0;
stop();
}
}, timerInterval);
}
};
// #endif
// #ifdef H5
const start = () => {
if (status.value === -1 || status.value === 0) {
status.value = 1;
_beforeStart();
console.log(timeFomartValue.value)
let lastTime = performance.now() - timerInterval;
const update = (currentTime : number) => {
const deltaTime = currentTime - lastTime;
if (deltaTime >= timerInterval) {
lastTime = currentTime;
const p = times.value - timerInterval
times.value = Number(p.toFixed(0))
if (times.value >= 0) {
_change(timeFomartValue.value)
}
if (times.value <= 0) {
times.value = 0;
stop();
}
}
if (status.value === 1) {
animationFrameId = requestAnimationFrame(update);
}
};
animationFrameId = requestAnimationFrame(update);
}
};
// #endif
const stop = () => {
if (timer !== null) {
clearInterval(timer);
timer = null;
}
if (animationFrameId !== null) {
cancelAnimationFrame(animationFrameId); // 取消动画帧请求
animationFrameId = null;
}
status.value = 0;
_timeEnd();
};
const restart = () => {
stop();
times.value = calculateRemainingTime();
start();
};
// 监听 totalTime 和 unit 变化,重新计算 times
watch([() => options.totalTime, () => options.unit], () => {
times.value = calculateRemainingTime();
});
function beforeStart(call : () => void) {
_beforeStart = call;
}
function timeEnd(call : () => void) {
_timeEnd = call;
}
function change(call : (n : number) => void) {
_change = call;
}
function calculateRemainingTime() : number {
switch (unit) {
case 'ms':
return totalTime;
case 'ss':
return totalTime * 1000;
case 'mm':
return totalTime * 60000;
case 'hh':
return totalTime * 3600000;
case 'dd':
return totalTime * 86400000;
default:
return totalTime;
}
};
const formatTime = (time : number) : FormattedTime => {
const years = Math.floor(time / (1000 * 60 * 60 * 24 * 365)); // 计算年份
const days = Math.floor((time % (1000 * 60 * 60 * 24 * 365)) / (1000 * 60 * 60 * 24));
const hours = Math.floor((time % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((time % (1000 * 60)) / 1000);
const milliseconds = time % 1000;
return { year: years, day: days, hour: hours, minute: minutes, second: seconds, millisecond: milliseconds };
};
const formattedTime = computed(() => {
let p = formatTime(times.value);
return (temForamt ?: string) => {
let fat = temForamt || format
return fat
.replace('yy', String(p.year))
.replace('dd', String(p.day))
.replace('hh', String(p.hour))
.replace('mm', String(p.minute))
.replace('ss', String(p.second))
.replace('ms', String(p.millisecond))
}
});
const timeObj = computed(() => formatTime(times.value)); // 计算 timeObj
return {
times: timeFomartValue,
formattedTime,
timeObj,
status: computed(() => status.value),
start,
stop,
restart,
beforeStart,
timeEnd,
change
};
}