framer-motion#useViewportScroll TypeScript Examples
The following examples show how to use
framer-motion#useViewportScroll.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: useInViewScroll.ts From framer-motion-hooks with MIT License | 6 votes |
useInViewScroll = (
el: RefObject<HTMLElement>,
options: IOptions = {}
): MotionValue<number> => {
const progress = useMotionValue(0)
const { scrollY } = useViewportScroll()
useEffect(() => {
const handleScrollProgress = () => {
const node = el.current
if (!node) return
const threshold = options.threshold || 0
const elPosY = node.getBoundingClientRect().top + scrollY.get()
const elHeight = node.scrollHeight
const viewIntersect = Math.max(elPosY - window.innerHeight, 0)
const current = scrollY.get() - viewIntersect - threshold
const total = Math.min(window.innerHeight, elPosY) + elHeight - threshold
const quotient = current / total
if (quotient > 0 && quotient < 1) {
progress.set(quotient)
}
}
handleScrollProgress()
const unsubscribeFromScroll = scrollY.onChange(handleScrollProgress)
return () => unsubscribeFromScroll()
}, [el, options])
return progress
}
Example #2
Source File: parallax.tsx From samuelkraft-next with MIT License | 6 votes |
Parallax = ({ children, offset = 50, clampInitial, clampFinal }: ParallaxProps): JSX.Element => {
const prefersReducedMotion = useReducedMotion()
const [elementTop, setElementTop] = useState(0)
const [clientHeight, setClientHeight] = useState(0)
const ref = useRef(null)
const { scrollY } = useViewportScroll()
const initial = elementTop - clientHeight
const final = elementTop + offset
const yRange = useTransform(scrollY, [initial, final], [clampInitial ? 0 : offset, clampFinal ? 0 : -offset])
const y = useSpring(yRange, { stiffness: 400, damping: 90 })
useLayoutEffect(() => {
const element = ref.current
const onResize = () => {
setElementTop(element.getBoundingClientRect().top + window.scrollY || window.pageYOffset)
setClientHeight(window.innerHeight)
}
onResize()
window.addEventListener('resize', onResize)
return () => window.removeEventListener('resize', onResize)
}, [ref])
// Don't parallax if the user has "reduced motion" enabled
if (prefersReducedMotion) {
return <>{children}</>
}
return (
<motion.div ref={ref} style={{ y }}>
{children}
</motion.div>
)
}
Example #3
Source File: Parallax.tsx From vignette-web with MIT License | 5 votes |
Parallax = ({
children,
id,
offset = 30,
className,
fadeIn,
}: ParallaxProps): JSX.Element => {
const prefersReducedMotion = useReducedMotion()
const [elementTop, setElementTop] = useState(0)
const [clientHeight, setClientHeight] = useState(0)
const ref = useRef<HTMLDivElement>(null)
const { scrollY } = useViewportScroll()
const initial = elementTop - clientHeight
const final = elementTop + offset
const router = useRouter()
const yRange = useTransform(scrollY, [initial, final], [offset, -offset], {
clamp: true,
})
const y = useSpring(yRange, { stiffness: 400, damping: 90 })
useEffect(() => {
const element = ref.current
const onResize = () => {
if (element) {
setElementTop(
element.getBoundingClientRect().top + window.scrollY ||
window.pageYOffset,
)
}
setClientHeight(window.innerHeight)
}
onResize()
window.addEventListener(`resize`, onResize)
return () => window.removeEventListener(`resize`, onResize)
}, [ref, router.pathname])
// Don't parallax if the user has "reduced motion" enabled
if (prefersReducedMotion) {
return <>{children}</>
}
return (
<motion.div
id={id}
className={className}
ref={ref}
style={{ y }}
transition={fadeIn ? { delay: 0.15, duration: 0.3 } : {}}
initial={fadeIn && { opacity: 0 }}
whileInView={fadeIn ? { opacity: 1 } : {}}
viewport={{ once: true }}
>
{children}
</motion.div>
)
}