Using framer-motion and react-intersection-observer to fade in images on load and scroll
14 replies
Last updated: Mar 15, 2022
L
hello! someone has an example or plugin to fadein next/images when loads ?
Mar 12, 2022, 12:40 AM
L
nice! I’ll give it a closer 👀
user E
Mar 12, 2022, 1:45 AM
T
What was the answer to this?
Mar 13, 2022, 1:41 AM
L
user M
I make it works using framer-Motion connected with two useState one to trigger when my image is loaded and another useState to trigger when my image is on the viewport.• framer-motion for the animation job
• react-intersection-observer for the element in viewport true/false
• onLoadingComplete from next/image to set true/false
thanks for the suggestion
user E
🙏Mar 14, 2022, 3:31 AM
I
user S
You don't need to use react-intersection-observer for this, take a look at
https://www.framer.com/docs/examples/#scroll-triggered-animations and whileInView and viewport.
Sample:
const bounceVariants: Variants = { offscreen: { y: 100, opacity: 0 }, onscreen: { y: 0, opacity: 1, transition: { type: "spring", bounce: 0.3, duration: 1.0 } } }; const BounceInScroll = ({ children}) => ( <motion.div initial="offscreen" whileInView="onscreen" viewport={{ once: true, amount: 0.4 }} data-testid="bounceinscroll" > <motion.div variants={bounceVariants}>{children}</motion.div> </motion.div> );
Mar 14, 2022, 5:41 PM
L
This is so nice!! way less code to handle 🙌
Mar 14, 2022, 6:43 PM
L
import { motion } from "framer-motion"; const FadeElement = ({ children, hasBeenLoaded, getIndex }) => { return ( <motion.div initial={{ opacity: 0 }} whileInView={{ opacity: hasBeenLoaded ? 1 : 0 }} transition={{ duration: 0.2, delay: getIndex * 0.1 }} viewport={{ once: true }} > {children} </motion.div> ); }; export default FadeElement;
Mar 14, 2022, 7:01 PM
I
What's hasBeenLoaded?
Mar 14, 2022, 7:03 PM
L
is for when next/image set true to
onLoadingComplete
Mar 14, 2022, 7:04 PM
L
probably this is pretty messy, but can give you a better perspective, I started to read about react and next just a month ago 👶
const Thumbnails = () => { const [loaded, setLoaded] = useState(false); return ( <FadeElement hasBeenLoaded={loaded} getIndex={id}> <Image src={urlFor(mainImage).url()} alt="alt" layout="fill" loading="lazy" objectFit="cover" onLoadingComplete={() => setLoaded(true)} /> </FadeElement> ); }; export default Thumbnails;
Mar 14, 2022, 7:13 PM
I
I don't think you need the hasBeenLoaded, you can just animate it when it it comes into scroll view, though
Mar 14, 2022, 7:16 PM
I
I don't think you need the hasBeenLoaded, you can just animate it when it it comes into scroll view, though
Mar 14, 2022, 7:16 PM
L
interesting, makes kind of sense! I’ll make a few tests.. my question is what happens if the motion.div is inside the viewport ✅ but the image is still loading ⏳
Mar 14, 2022, 7:20 PM
I
I'm no framer expert, you have to experiment and try it out yourself. 😉
Mar 14, 2022, 9:17 PM
T
Woah thanks so much!
Mar 15, 2022, 2:10 AM
Sanity– build remarkable experiences at scale
Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.