Skip to content

Instantly share code, notes, and snippets.

@tol-is
Created October 4, 2019 09:47
Show Gist options
  • Save tol-is/d442f7de5e25d22d213b2a003654da7d to your computer and use it in GitHub Desktop.
Save tol-is/d442f7de5e25d22d213b2a003654da7d to your computer and use it in GitHub Desktop.
Parallax Component with Framer Motion
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 (
<motion.div ref={ref} style={{ x, y }} {...rest}>
{children}
</motion.div>
);
};
Parallax.defaultProps = {
rangeX: [0, 0],
rangeY: [0, 0],
};
export default Parallax;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment