import { useElementBounding, useIntersectionObserver, useWindowSize, } from '@vueuse/core' import { ref } from 'vue' import { mapRange, clamp } from '@/libs/math' import useLenis from '@/composables/useLenis' const { height: wHeight } = useWindowSize() export const useScrollProgress = (el, callback, entry = 0.5, exit = 0.5) => { const isActive = ref(true) const smoothProgress = ref(0) const { height, top } = useElementBounding(el) const isIntersected = ref(false) const { stop } = useIntersectionObserver(el, ([{ isIntersecting }]) => { isIntersected.value = isIntersecting }) useLenis(({ scroll }) => { if (!isActive.value) return if (!height.value || !wHeight.value) return if (!isIntersected.value) return const pageTop = scroll + top.value const start = pageTop - wHeight.value * entry const end = pageTop + height.value - wHeight.value * exit let rawProgress = mapRange(start, end, scroll, 0, 1) rawProgress = clamp(0, rawProgress, 1) smoothProgress.value += (rawProgress - smoothProgress.value) * 0.1 callback?.(smoothProgress.value) }) const destroy = () => { isActive.value = false stop?.() } return { destroy } }