While using Framer Motion API to create interaction and animations on my site, I can not find how to use it in order to trigger an animation when something is on the screen.
For example, this SVG draws correctly, but Framer does not wait for the element to be on the viewport and triggers it right after loading site:
import React, { Component } from 'react'
import { motion } from "framer-motion";
class IsometricScreen extends Component {
constructor() {
super()
this.icon = {
hidden: { pathLength: 0 },
visible: { pathLength: 1 }
}
}
render() {
return (
<motion.svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 1000" className="svg-mobile">
<motion.path
d="M418,988.93H82c-39.76,0-72-32.24-72-72V83.07c0-39.76,32.24-72,72-72h336c39.76,0,72,32.24,72,72v833.86
C490,956.69,457.76,988.93,418,988.93z"
variants={this.icon}
initial="hidden"
animate="visible"
transition={{
default: { duration: 2, ease: "easeInOut" }
}}
/>
</motion.svg>
)
}
}
export default IsometricScreen
Does Framer have a viewport detection triggerer to be implemented here?
Alternatively, you can use Intersection Observer, blends pretty well with React and framer motion.
import { useInView } from "react-intersection-observer"; // 1.9K gzipped
import { motion, useAnimation } from "framer-motion";
const Component = () => {
const animation = useAnimation();
const [ref, inView, entry] = useInView({ threshold: 0.1 });
useEffect(() => {
if (inView) {
animation.start("visible");
} else {
animation.start("hidden");
}
}, [animation, inView]);
const variants = {
visible: {
y: 0,
opacity: 1,
transition: { duration: 0.5, delayChilden: 0.2, staggerChildren: 0.1 },
},
hidden: {
y: enter,
opacity: 0,
},
}
return (
<motion.div
ref={ref}
animate={animation}
initial="hidden"
variants={{variants}}
/>
);
}
You can also refine your animation by looking at entry object (entering from top or bottom, etc)