import React, { useState, useRef, useEffect, useLayoutEffect } from 'react'; import { useViewportScroll, useTransform, motion } from 'framer-motion'; const Parallax = ({ rangeX, rangeY, children, ...rest }) => { const ref = useRef(); const [rangeStart, setRangeStart] = useState(0); const [rangeEnd, setRangeEnd] = useState(0); const { scrollY } = useViewportScroll(); useLayoutEffect(() => { const onResize = () => { const scrollPos = window.pageYOffset; const html = document.documentElement; const viewportHeight = window.innerHeight || html.clientHeight; const rect = ref.current.getBoundingClientRect(); let start = rect.top + scrollPos - viewportHeight; let end = rect.top + scrollPos + rect.height; setRangeStart(start); setRangeEnd(end); }; setTimeout(onResize, 350); window.addEventListener('resize', onResize); return () => window.removeEventListener('resize', onResize); }, [ref, rangeX, rangeX]); const y = useTransform( scrollY, [rangeStart, rangeEnd], [`${rangeY[0] * 100}%`, `${rangeY[1] * 100}%`] ); const x = useTransform( scrollY, [rangeStart, rangeEnd], [`${rangeX[0] * 100}%`, `${rangeX[1] * 100}%`] ); return ( {children} ); }; Parallax.defaultProps = { rangeX: [0, 0], rangeY: [0, 0], }; export default Parallax;