From 7d7450ddd98335f6d672670f4192baecaa62d1c2 Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Mon, 11 Sep 2023 17:49:08 +0800 Subject: [PATCH] Add prevent scroll control to HideScrollbar --- src/components/FitCenter.tsx | 2 +- src/components/FitFullScreen.tsx | 3 +- src/components/HideScrollbar.tsx | 60 ++++++++++++++++++++++++++++++-- src/pages/MainFramework.tsx | 37 ++++++++++++++++---- vite.config.ts | 5 --- 5 files changed, 92 insertions(+), 15 deletions(-) diff --git a/src/components/FitCenter.tsx b/src/components/FitCenter.tsx index ede8b2e..ea15292 100644 --- a/src/components/FitCenter.tsx +++ b/src/components/FitCenter.tsx @@ -1,7 +1,7 @@ import React from 'react' import '@/assets/css/fit-center.scss' -const FitCenter: React.FC = (props: PropsWithChildren) => { +const FitCenter: React.FC = (props) => { return ( <>
{props.children}
diff --git a/src/components/FitFullScreen.tsx b/src/components/FitFullScreen.tsx index e356c2c..2dbebbe 100644 --- a/src/components/FitFullScreen.tsx +++ b/src/components/FitFullScreen.tsx @@ -1,6 +1,7 @@ +import React from 'react' import '@/assets/css/fit-fullscreen.scss' -interface FitFullscreenProps extends PropsWithChildren { +interface FitFullscreenProps extends React.PropsWithChildren { zIndex?: number backgroundColor?: string } diff --git a/src/components/HideScrollbar.tsx b/src/components/HideScrollbar.tsx index 52a4644..815f7fd 100644 --- a/src/components/HideScrollbar.tsx +++ b/src/components/HideScrollbar.tsx @@ -1,5 +1,11 @@ +import React from 'react' import '@/assets/css/hide-scrollbar.scss' +interface HideScrollbarProps + extends React.DetailedHTMLProps, HTMLDivElement> { + isPreventScroll?: boolean +} + export interface HideScrollbarElement { scrollTo(x: number, y: number): void scrollX(x: number): void @@ -32,11 +38,46 @@ export interface HideScrollbarElement { ): void } -const HideScrollbar = forwardRef((props, ref) => { +const HideScrollbar = forwardRef((props, ref) => { const rootRef = useRef(null) const [verticalScrollbarWidth, setVerticalScrollbarWidth] = useState(0) const [horizontalScrollbarWidth, setHorizontalScrollbarWidth] = useState(0) + const { isPreventScroll, ..._props } = props + + const handleDefaultWheel = (event: WheelEvent) => { + event.preventDefault() + } + + const handleDefaultTouchmove = (event: TouchEvent) => { + event.preventDefault() + } + + const handleDefaultClickMiddleMouseButton = (event: MouseEvent) => { + if (event.button === 1) { + event.preventDefault() + } + } + + const handleDefaultKeyDown = (event: KeyboardEvent) => { + if ( + [ + 'ArrowUp', + 'ArrowDown', + 'ArrowLeft', + 'ArrowRight', + ' ', + '', + 'PageUp', + 'PageDown', + 'Home', + 'End' + ].find((value) => value === event.key) + ) { + event.preventDefault() + } + } + useImperativeHandle( ref, () => { @@ -143,11 +184,24 @@ const HideScrollbar = forwardRef((props }, 1000) window.addEventListener('resize', windowResizeListener()) + if (isPreventScroll) { + rootRef.current?.addEventListener('wheel', handleDefaultWheel, { passive: false }) + rootRef.current?.addEventListener('touchmove', handleDefaultTouchmove, { + passive: false + }) + rootRef.current?.addEventListener('mousedown', handleDefaultClickMiddleMouseButton) + rootRef.current?.addEventListener('keydown', handleDefaultKeyDown) + } else { + rootRef.current?.removeEventListener('wheel', handleDefaultWheel) + rootRef.current?.removeEventListener('touchmove', handleDefaultTouchmove) + rootRef.current?.removeEventListener('mousedown', handleDefaultClickMiddleMouseButton) + rootRef.current?.removeEventListener('keydown', handleDefaultKeyDown) + } return () => { window.removeEventListener('resize', windowResizeListener) } - }, []) + }, [isPreventScroll]) return ( <> @@ -155,10 +209,12 @@ const HideScrollbar = forwardRef((props
{props.children}
diff --git a/src/pages/MainFramework.tsx b/src/pages/MainFramework.tsx index 23ff379..d885588 100644 --- a/src/pages/MainFramework.tsx +++ b/src/pages/MainFramework.tsx @@ -9,30 +9,54 @@ export const MainFrameworkContext = createContext<{ navbarHidden: boolean setNavbarHidden: (newValue: boolean) => void } - hideScrollbarRef: RefObject + preventScrollState: { + preventScroll: boolean + setPreventScroll: (newValue: boolean) => void + } + hideScrollbarRef: React.RefObject }>({ navbarHiddenState: { navbarHidden: false, setNavbarHidden: () => undefined }, - hideScrollbarRef: createRef() + hideScrollbarRef: createRef(), + preventScrollState: { + preventScroll: false, + setPreventScroll: () => undefined + } }) const MainFramework: React.FC = () => { - const [navbarHidden, setNavbarHidden] = useState(true) - - const hideScrollbarRef = useRef(null) const routeId = useMatches()[1].id const routeChildren = router.routes[0].children?.find((value) => value.id === routeId)?.children const pathname = useLocation().pathname + + const hideScrollbarRef = useRef(null) + + const [navbarHidden, setNavbarHidden] = useState(true) + const [preventScroll, setPreventScroll] = useState(false) + useEffect(() => { setNavbarHidden(false) }, [pathname]) + const handleOnWheel = useCallback((event: React.WheelEvent) => { + console.log(event) + }, []) + + const handleOnScroll = useCallback((event: React.UIEvent) => { + console.log(event) + }, []) + return ( <> - +