fix(hooks): refactor useCountDown hook for improved countdown logic and clarity.
This commit is contained in:
parent
7fb5c72f7e
commit
dfb647a82c
@ -2,40 +2,59 @@ import { computed, onScopeDispose, ref } from 'vue';
|
|||||||
import { useRafFn } from '@vueuse/core';
|
import { useRafFn } from '@vueuse/core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* count down
|
* A hook for implementing a countdown timer. It uses `requestAnimationFrame` for smooth and accurate timing,
|
||||||
|
* independent of the screen refresh rate.
|
||||||
*
|
*
|
||||||
* @param seconds - count down seconds
|
* @param initialSeconds - The total number of seconds for the countdown.
|
||||||
*/
|
*/
|
||||||
export default function useCountDown(seconds: number) {
|
export default function useCountDown(initialSeconds: number) {
|
||||||
const FPS_PER_SECOND = 60;
|
const remainingSeconds = ref(0);
|
||||||
|
|
||||||
const fps = ref(0);
|
const count = computed(() => Math.ceil(remainingSeconds.value));
|
||||||
|
|
||||||
const count = computed(() => Math.ceil(fps.value / FPS_PER_SECOND));
|
const isCounting = computed(() => remainingSeconds.value > 0);
|
||||||
|
|
||||||
const isCounting = computed(() => fps.value > 0);
|
|
||||||
|
|
||||||
const { pause, resume } = useRafFn(
|
const { pause, resume } = useRafFn(
|
||||||
() => {
|
({ delta }) => {
|
||||||
if (fps.value > 0) {
|
// delta: milliseconds elapsed since the last frame.
|
||||||
fps.value -= 1;
|
|
||||||
} else {
|
// If countdown already reached zero or below, ensure it's 0 and stop.
|
||||||
|
if (remainingSeconds.value <= 0) {
|
||||||
|
remainingSeconds.value = 0;
|
||||||
|
pause();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate seconds passed since the last frame.
|
||||||
|
const secondsPassed = delta / 1000;
|
||||||
|
remainingSeconds.value -= secondsPassed;
|
||||||
|
|
||||||
|
// If countdown has finished after decrementing.
|
||||||
|
if (remainingSeconds.value <= 0) {
|
||||||
|
remainingSeconds.value = 0;
|
||||||
pause();
|
pause();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: false }
|
{ immediate: false } // The timer does not start automatically.
|
||||||
);
|
);
|
||||||
|
|
||||||
function start(updateSeconds: number = seconds) {
|
/**
|
||||||
fps.value = FPS_PER_SECOND * updateSeconds;
|
* Starts the countdown.
|
||||||
|
*
|
||||||
|
* @param [updatedSeconds=initialSeconds] - Optionally, start with a new duration. Default is `initialSeconds`
|
||||||
|
*/
|
||||||
|
function start(updatedSeconds: number = initialSeconds) {
|
||||||
|
remainingSeconds.value = updatedSeconds;
|
||||||
resume();
|
resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Stops the countdown and resets the remaining time to 0. */
|
||||||
function stop() {
|
function stop() {
|
||||||
fps.value = 0;
|
remainingSeconds.value = 0;
|
||||||
pause();
|
pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure the rAF loop is cleaned up when the component is unmounted.
|
||||||
onScopeDispose(() => {
|
onScopeDispose(() => {
|
||||||
pause();
|
pause();
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user