v1.0-230926 #27
@@ -4,16 +4,20 @@ import '@/assets/css/components/common/hide-scrollbar.scss'
|
|||||||
interface HideScrollbarProps
|
interface HideScrollbarProps
|
||||||
extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
|
extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
|
||||||
isPreventScroll?: boolean
|
isPreventScroll?: boolean
|
||||||
|
isPreventVerticalScroll?: boolean
|
||||||
|
isPreventHorizontalScroll?: boolean
|
||||||
|
isShowVerticalScrollbar?: boolean
|
||||||
|
isShowHorizontalScrollbar?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HideScrollbarElement {
|
export interface HideScrollbarElement {
|
||||||
scrollTo(x: number, y: number): void
|
scrollTo(x: number, y: number, smooth?: boolean): void
|
||||||
scrollX(x: number): void
|
scrollX(x: number, smooth?: boolean): void
|
||||||
scrollY(y: number): void
|
scrollY(y: number, smooth?: boolean): void
|
||||||
scrollLeft(length: number): void
|
scrollLeft(length: number, smooth?: boolean): void
|
||||||
scrollRight(length: number): void
|
scrollRight(length: number, smooth?: boolean): void
|
||||||
scrollUp(length: number): void
|
scrollUp(length: number, smooth?: boolean): void
|
||||||
scrollDown(length: number): void
|
scrollDown(length: number, smooth?: boolean): void
|
||||||
getX(): number
|
getX(): number
|
||||||
getY(): number
|
getY(): number
|
||||||
addEventListenerWithType<K extends keyof HTMLElementEventMap>(
|
addEventListenerWithType<K extends keyof HTMLElementEventMap>(
|
||||||
@@ -40,19 +44,79 @@ export interface HideScrollbarElement {
|
|||||||
|
|
||||||
const HideScrollbar = forwardRef<HideScrollbarElement, HideScrollbarProps>((props, ref) => {
|
const HideScrollbar = forwardRef<HideScrollbarElement, HideScrollbarProps>((props, ref) => {
|
||||||
const rootRef = useRef<HTMLDivElement>(null)
|
const rootRef = useRef<HTMLDivElement>(null)
|
||||||
|
const lastTouchPosition = useRef<{ x: number; y: number }>({ x: -1, y: -1 })
|
||||||
const [verticalScrollbarWidth, setVerticalScrollbarWidth] = useState(0)
|
const [verticalScrollbarWidth, setVerticalScrollbarWidth] = useState(0)
|
||||||
const [horizontalScrollbarWidth, setHorizontalScrollbarWidth] = useState(0)
|
const [horizontalScrollbarWidth, setHorizontalScrollbarWidth] = useState(0)
|
||||||
|
|
||||||
const { isPreventScroll, ..._props } = props
|
const {
|
||||||
const handleDefaultWheel = useCallback((event: WheelEvent) => {
|
isPreventScroll,
|
||||||
if (!event.altKey && !event.ctrlKey) {
|
isPreventVerticalScroll,
|
||||||
event.preventDefault()
|
isPreventHorizontalScroll,
|
||||||
}
|
isShowVerticalScrollbar,
|
||||||
}, [])
|
isShowHorizontalScrollbar,
|
||||||
|
..._props
|
||||||
|
} = props
|
||||||
|
|
||||||
const handleDefaultTouchmove = useCallback((event: TouchEvent) => {
|
const handleDefaultWheel = useCallback(
|
||||||
|
(event: WheelEvent) => {
|
||||||
|
if (!event.altKey && !event.ctrlKey) {
|
||||||
|
if (isPreventScroll) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
}, [])
|
return
|
||||||
|
}
|
||||||
|
if (isPreventVerticalScroll && !event.shiftKey && !event.deltaX) {
|
||||||
|
event.preventDefault()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (isPreventHorizontalScroll && (event.shiftKey || !event.deltaY)) {
|
||||||
|
event.preventDefault()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[isPreventScroll, isPreventHorizontalScroll, isPreventVerticalScroll]
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleDefaultTouchStart = useCallback(
|
||||||
|
(event: TouchEvent) => {
|
||||||
|
if (event.touches.length !== 1 || isPreventScroll) {
|
||||||
|
lastTouchPosition.current = { x: -1, y: -1 }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const { clientX, clientY } = event.touches[0]
|
||||||
|
lastTouchPosition.current = { x: clientX, y: clientY }
|
||||||
|
},
|
||||||
|
[isPreventScroll]
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleDefaultTouchmove = useCallback(
|
||||||
|
(event: TouchEvent) => {
|
||||||
|
event.preventDefault()
|
||||||
|
if (event.touches.length !== 1 || isPreventScroll) {
|
||||||
|
lastTouchPosition.current = { x: -1, y: -1 }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { clientX, clientY } = event.touches[0]
|
||||||
|
|
||||||
|
if (!isPreventVerticalScroll) {
|
||||||
|
rootRef.current?.scrollTo({
|
||||||
|
top: rootRef.current?.scrollTop + (lastTouchPosition.current.y - clientY),
|
||||||
|
behavior: 'instant'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPreventHorizontalScroll) {
|
||||||
|
rootRef.current?.scrollTo({
|
||||||
|
left: rootRef.current?.scrollLeft + (lastTouchPosition.current.x - clientX),
|
||||||
|
behavior: 'instant'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
lastTouchPosition.current = { x: clientX, y: clientY }
|
||||||
|
},
|
||||||
|
[isPreventScroll, isPreventHorizontalScroll, isPreventVerticalScroll]
|
||||||
|
)
|
||||||
|
|
||||||
const handleDefaultClickMiddleMouseButton = useCallback((event: MouseEvent) => {
|
const handleDefaultClickMiddleMouseButton = useCallback((event: MouseEvent) => {
|
||||||
if (event.button === 1) {
|
if (event.button === 1) {
|
||||||
@@ -60,8 +124,10 @@ const HideScrollbar = forwardRef<HideScrollbarElement, HideScrollbarProps>((prop
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleDefaultKeyDown = (event: KeyboardEvent) => {
|
const handleDefaultKeyDown = useCallback(
|
||||||
|
(event: KeyboardEvent) => {
|
||||||
if (
|
if (
|
||||||
|
isPreventScroll &&
|
||||||
[
|
[
|
||||||
'ArrowUp',
|
'ArrowUp',
|
||||||
'ArrowDown',
|
'ArrowDown',
|
||||||
@@ -77,53 +143,69 @@ const HideScrollbar = forwardRef<HideScrollbarElement, HideScrollbarProps>((prop
|
|||||||
) {
|
) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
isPreventVerticalScroll &&
|
||||||
|
['ArrowUp', 'ArrowDown', ' ', '', 'PageUp', 'PageDown', 'Home', 'End'].find(
|
||||||
|
(value) => value === event.key
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
isPreventHorizontalScroll &&
|
||||||
|
['ArrowLeft', 'ArrowRight'].find((value) => value === event.key)
|
||||||
|
) {
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[isPreventScroll, isPreventHorizontalScroll, isPreventVerticalScroll]
|
||||||
|
)
|
||||||
|
|
||||||
useImperativeHandle<HideScrollbarElement, HideScrollbarElement>(
|
useImperativeHandle<HideScrollbarElement, HideScrollbarElement>(
|
||||||
ref,
|
ref,
|
||||||
() => {
|
() => {
|
||||||
return {
|
return {
|
||||||
scrollTo(x, y) {
|
scrollTo(x, y, smooth?: boolean) {
|
||||||
rootRef.current?.scrollTo({
|
rootRef.current?.scrollTo({
|
||||||
left: x,
|
left: x,
|
||||||
top: y,
|
top: y,
|
||||||
behavior: 'smooth'
|
behavior: smooth === false ? 'instant' : 'smooth'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
scrollX(x) {
|
scrollX(x, smooth?: boolean) {
|
||||||
rootRef.current?.scrollTo({
|
rootRef.current?.scrollTo({
|
||||||
left: x,
|
left: x,
|
||||||
behavior: 'smooth'
|
behavior: smooth === false ? 'instant' : 'smooth'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
scrollY(y) {
|
scrollY(y, smooth?: boolean) {
|
||||||
rootRef.current?.scrollTo({
|
rootRef.current?.scrollTo({
|
||||||
top: y,
|
top: y,
|
||||||
behavior: 'smooth'
|
behavior: smooth === false ? 'instant' : 'smooth'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
scrollLeft(length) {
|
scrollLeft(length, smooth?: boolean) {
|
||||||
rootRef.current?.scrollTo({
|
rootRef.current?.scrollTo({
|
||||||
left: rootRef.current?.scrollLeft - length,
|
left: rootRef.current?.scrollLeft - length,
|
||||||
behavior: 'smooth'
|
behavior: smooth === false ? 'instant' : 'smooth'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
scrollRight(length) {
|
scrollRight(length, smooth?: boolean) {
|
||||||
rootRef.current?.scrollTo({
|
rootRef.current?.scrollTo({
|
||||||
left: rootRef.current?.scrollLeft + length,
|
left: rootRef.current?.scrollLeft + length,
|
||||||
behavior: 'smooth'
|
behavior: smooth === false ? 'instant' : 'smooth'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
scrollUp(length) {
|
scrollUp(length, smooth?: boolean) {
|
||||||
rootRef.current?.scrollTo({
|
rootRef.current?.scrollTo({
|
||||||
top: rootRef.current?.scrollTop - length,
|
top: rootRef.current?.scrollTop - length,
|
||||||
behavior: 'smooth'
|
behavior: smooth === false ? 'instant' : 'smooth'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
scrollDown(length) {
|
scrollDown(length, smooth?: boolean) {
|
||||||
rootRef.current?.scrollTo({
|
rootRef.current?.scrollTo({
|
||||||
top: rootRef.current?.scrollTop + length,
|
top: rootRef.current?.scrollTop + length,
|
||||||
behavior: 'smooth'
|
behavior: smooth === false ? 'instant' : 'smooth'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getX() {
|
getX() {
|
||||||
@@ -185,8 +267,11 @@ const HideScrollbar = forwardRef<HideScrollbarElement, HideScrollbarProps>((prop
|
|||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
window.addEventListener('resize', windowResizeListener())
|
window.addEventListener('resize', windowResizeListener())
|
||||||
if (isPreventScroll) {
|
if (isPreventScroll || isPreventVerticalScroll || isPreventHorizontalScroll) {
|
||||||
rootRef.current?.addEventListener('wheel', handleDefaultWheel, { passive: false })
|
rootRef.current?.addEventListener('wheel', handleDefaultWheel, { passive: false })
|
||||||
|
rootRef.current?.addEventListener('touchstart', handleDefaultTouchStart, {
|
||||||
|
passive: false
|
||||||
|
})
|
||||||
rootRef.current?.addEventListener('touchmove', handleDefaultTouchmove, {
|
rootRef.current?.addEventListener('touchmove', handleDefaultTouchmove, {
|
||||||
passive: false
|
passive: false
|
||||||
})
|
})
|
||||||
@@ -194,6 +279,7 @@ const HideScrollbar = forwardRef<HideScrollbarElement, HideScrollbarProps>((prop
|
|||||||
rootRef.current?.addEventListener('keydown', handleDefaultKeyDown)
|
rootRef.current?.addEventListener('keydown', handleDefaultKeyDown)
|
||||||
} else {
|
} else {
|
||||||
rootRef.current?.removeEventListener('wheel', handleDefaultWheel)
|
rootRef.current?.removeEventListener('wheel', handleDefaultWheel)
|
||||||
|
rootRef.current?.removeEventListener('touchstart', handleDefaultTouchStart)
|
||||||
rootRef.current?.removeEventListener('touchmove', handleDefaultTouchmove)
|
rootRef.current?.removeEventListener('touchmove', handleDefaultTouchmove)
|
||||||
rootRef.current?.removeEventListener('mousedown', handleDefaultClickMiddleMouseButton)
|
rootRef.current?.removeEventListener('mousedown', handleDefaultClickMiddleMouseButton)
|
||||||
rootRef.current?.removeEventListener('keydown', handleDefaultKeyDown)
|
rootRef.current?.removeEventListener('keydown', handleDefaultKeyDown)
|
||||||
@@ -204,9 +290,13 @@ const HideScrollbar = forwardRef<HideScrollbarElement, HideScrollbarProps>((prop
|
|||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
handleDefaultClickMiddleMouseButton,
|
handleDefaultClickMiddleMouseButton,
|
||||||
|
handleDefaultKeyDown,
|
||||||
|
handleDefaultTouchStart,
|
||||||
handleDefaultTouchmove,
|
handleDefaultTouchmove,
|
||||||
handleDefaultWheel,
|
handleDefaultWheel,
|
||||||
isPreventScroll
|
isPreventHorizontalScroll,
|
||||||
|
isPreventScroll,
|
||||||
|
isPreventVerticalScroll
|
||||||
])
|
])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const MainFramework: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<HideScrollbar ref={hideScrollbarRef} isPreventScroll={preventScroll}>
|
<HideScrollbar ref={hideScrollbarRef} isPreventVerticalScroll={preventScroll}>
|
||||||
<div className={'body'}>
|
<div className={'body'}>
|
||||||
<header className={'nav' + (navbarHidden ? ' hide' : '')}>
|
<header className={'nav' + (navbarHidden ? ' hide' : '')}>
|
||||||
<a className={'logo'} href={'https://fatweb.top'}>
|
<a className={'logo'} href={'https://fatweb.top'}>
|
||||||
|
|||||||
Reference in New Issue
Block a user