z自定义指令
This commit is contained in:
63
src/directives/scroll-progress.ts
Normal file
63
src/directives/scroll-progress.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 监听滚动条 滚动进度变化
|
||||
* 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)
|
||||
}
|
||||
})
|
||||
};
|
||||
Reference in New Issue
Block a user