UNPKG

@oiij/use

Version:

Som Composable Functions for Vue 3

69 lines (67 loc) 1.99 kB
import { createEventHook, useRafFn } from "@vueuse/core"; import { computed, readonly, ref, toValue, watchEffect } from "vue"; //#region src/composables/use-number-animation.ts const easingFns = { linear: (t) => t, easeIn: (t) => t * t, easeOut: (t) => 1 - (1 - t) ** 2, easeInOut: (t) => t < .5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2 }; function useNumberAnimation(to, options) { const { from = 0, manual = false, duration = 1 * 1e3, precision = 2, easing = "linear" } = options ?? {}; const easingFn = typeof easing === "function" ? easing : easingFns[easing] || easingFns.linear; const currentValue = ref(from); const targetValue = ref(toValue(to)); watchEffect(() => { if (targetValue.value !== toValue(to)) { targetValue.value = toValue(to); start(); } }); const startTime = ref(0); const isFirst = ref(true); const onStartHook = createEventHook(); const onEndHook = createEventHook(); const onProgressHook = createEventHook(); const { pause, resume, isActive } = useRafFn(() => { const elapsed = performance.now() - startTime.value; if (isFirst.value) { isFirst.value = false; onStartHook.trigger(); } const progress = Math.min(elapsed / duration, 1); const easedProgress = easingFn(progress); currentValue.value = from + (targetValue.value - from) * easedProgress; if (progress >= 1) { currentValue.value = targetValue.value; pause(); onEndHook.trigger(); return; } onProgressHook.trigger(currentValue.value); }, { immediate: false }); function start() { startTime.value = performance.now(); isFirst.value = true; resume(); } function stop() { pause(); onEndHook.trigger(); currentValue.value = targetValue.value; } if (!manual) start(); return { value: readonly(computed(() => currentValue.value.toFixed(precision))), isActive, start, stop, pause, resume, onStart: onStartHook.on, onEnd: onEndHook.on, onProgress: onProgressHook.on }; } //#endregion export { useNumberAnimation };