Created
November 27, 2020 12:24
-
-
Save smashercosmo/0141e11ac7cbfe21ee979f629cf3083b to your computer and use it in GitHub Desktop.
useDragScroll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from 'react' | |
import { useDrag } from 'react-use-gesture' | |
import { useSpring, config } from '@react-spring/web' | |
function clamp(min: number, val: number, max: number) { | |
return Math.min(Math.max(min, val), max) | |
} | |
const isServer = typeof window === 'undefined' | |
function useDragScroll() { | |
const scrollX = isServer ? 0 : window.scrollX | |
const scrollY = isServer ? 0 : window.scrollY | |
const isMouseAction = React.useRef(false) | |
const [values] = useSpring( | |
{ | |
from: { | |
x: scrollX, | |
y: scrollY, | |
}, | |
onChange: { | |
x(value: number) { | |
document.documentElement.scrollLeft = value | |
}, | |
y(value: number) { | |
document.documentElement.scrollTop = value | |
}, | |
}, | |
config: config.slow, | |
}, | |
[], | |
) | |
function setX(value: number) { | |
const minScrollLeft = 0 | |
const maxScrollLeft = | |
document.documentElement.scrollWidth - | |
document.documentElement.clientWidth | |
const to = clamp(minScrollLeft, values.x.goal + value, maxScrollLeft) | |
values.x.start({ to }) | |
} | |
function setY(value: number) { | |
const minScrollTop = 0 | |
const maxScrollTop = | |
document.documentElement.scrollHeight - | |
document.documentElement.clientHeight | |
const to = clamp(minScrollTop, values.y.goal + value, maxScrollTop) | |
values.y.start({ to }) | |
} | |
React.useEffect(() => { | |
function handleWheel() { | |
if (values.x.is('ACTIVE') || values.y.is('ACTIVE')) { | |
values.x.stop() | |
values.y.stop() | |
} | |
values.x.set(window.scrollX) | |
values.y.set(window.scrollY) | |
} | |
function handlePointerDown(event: PointerEvent) { | |
if (event.pointerType === 'mouse') { | |
isMouseAction.current = true | |
} | |
} | |
function handlePointerUp() { | |
isMouseAction.current = false | |
} | |
window.addEventListener('wheel', handleWheel) | |
window.addEventListener('pointerdown', handlePointerDown) | |
window.addEventListener('pointerup', handlePointerUp) | |
return function teardown() { | |
window.removeEventListener('wheel', handleWheel) | |
window.removeEventListener('pointerdown', handlePointerDown) | |
window.removeEventListener('pointerup', handlePointerUp) | |
} | |
}, [values]) | |
useDrag( | |
({ delta: [x, y] }) => { | |
if (isMouseAction.current) { | |
setX(-x) | |
setY(-y) | |
} | |
}, | |
{ | |
domTarget: isServer ? undefined : document.documentElement, | |
}, | |
) | |
} | |
export { useDragScroll } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment