/** * 监听滚动条 滚动进度变化 * v-scroll-progress.self="(p) => console.log(p)" * @modifiers self 监听当前元素的滚动进度变化 * @param params 滚动进度回调函数 * @param p 滚动进度 */ const rootMap = new Map() export default { name: 'scroll-progress', mounted(el: HTMLElement, binding: any) { const params = binding.value const { self } = binding.modifiers const paramsType = typeof params const obj = { onscroll: () => { }, el, root: self ? el : document, activeNum: 0, }; if (paramsType === 'function') { obj.onscroll = params } else if (paramsType === 'object') { if (params.onscroll) obj.onscroll = params.onscroll if (params.GetRoot) obj.root = params.GetRoot() if (params.hasOwnProperty('activeNum')) obj.activeNum = params.activeNum } requestAnimationFrame(() => handleScroll({ target: obj.root })) if (rootMap.has(obj.root)) { rootMap.get(obj.root).push(obj) return } rootMap.set(obj.root, [obj]) obj.root.addEventListener('scroll', handleScroll) }, beforeUnmount(el: HTMLElement, binding: any) { rootMap.forEach((objs, root) => { if (objs.some((v: any) => v.el === el)) { objs = objs.filter((v_: any) => v_.el !== el) rootMap.set(root, objs) } if (objs.length === 0) { root.removeEventListener('scroll', handleScroll) rootMap.delete(root) } }) }, }; function handleScroll(e: any) { const target = e.target const objs = rootMap.get(target) if (!objs || objs.length === 0) return const el = target === document ? document.documentElement : target as HTMLElement const num = el.scrollTop / (el.scrollHeight - el.clientHeight); const progress = Math.round(num * 100) objs.forEach((obj: any) => { obj?.onscroll(progress) if (obj.el) { let isActive = progress > obj.activeNum obj.el.classList.toggle('active', isActive) } }) };