export type ScrollListener = { source: Event; viewWidth: number; viewHeight: number; top: number; bottom: number; } export default class Scroller { private static instance: Scroller; listeners = new Map(); private constructor() { window.addEventListener("scroll", source => { // 滚动距离 const top = document.body.scrollTop || document.documentElement.scrollTop; // 可视高度 const viewWidth = document.documentElement.clientWidth || document.body.clientWidth; // 可视高度 const viewHeight = document.documentElement.clientHeight || document.body.clientHeight; // 滚动高度 const sH = document.documentElement.scrollHeight || document.body.scrollHeight; // 触发事件 const bottom = sH - top - viewHeight; this.listeners.forEach(listener => listener({ source, viewWidth, viewHeight, top, bottom } as ScrollListener)); }, true); } private static getInstance(): Scroller { if (!Scroller.instance) { Scroller.instance = new Scroller(); } return Scroller.instance; } /** * 添加监听 * * @param name 事件名 * @param listener 监听事件 */ public static addListener(name: string, listener: (event: ScrollListener) => void) { Scroller.getInstance().listeners.set(name, listener); } /** * 移除监听 * * @param name 事件名 */ public static removeListener(name: string) { Scroller.getInstance().listeners.delete(name); } /** 滚动至顶(平滑地) */ public static toTop() { document.body.scrollIntoView({behavior: "smooth"}); } /** 滚动至指定节点(平滑地) */ public static toElement(el: HTMLElement) { el.scrollIntoView({behavior: "smooth"}); } }