Reputation: 1694
I am creating a space viewer app and using Framer motion for the animations. What I am aiming for is the starting component that is called loading
will have an exit animation upon being clicked. However at the moment all of my components are failing to have exit animations. They simply lead to other components as if I was only using react-router.
My app.js looks like this
<AnimatePresence /* I have tried to put exitBeforeEnter here, it does nothing*/ >
<Route exact path="/" key="loading" component={Loading} />
<Route path="/sol" key="menu" component={Menu} />
And my loading
component looks like this
const loading = {
start: {
scale: 2,
},
out: {
scale: .1,
},
};
const pagetransition = {
duration: 2,
};
return(
<motion.div initial="start"
animate="in"
exit="out"
variants={loading}
transition={pagetransition} className="loadingScreen"
>
<NavLink to="/sol"><button ><p >Enter System</p></button></NavLink>
</motion.div>
At the moment, none of my pages have exit animations, but they do have entrance animations, so I know that I am not doing things totally wrong. I have a codesandbox where all of my code is visible.
Upvotes: 2
Views: 4024
Reputation: 516
I have made some changes in the code sandbox. Using Framer-Motion to do route transitions is quite easy but a little involved. First you have to use AnimatePresence
outside the <Switch> ... </Switch>
. Then you need to have some key in Switch
for Framer-motion to keep track of the routes.
We use location
for the key and inorder to use the useLocation()
hook in App.js, we'll need to surround <App />
in index.js
with Router
. So that's what I've done.
Here are the changes that I've explained until now.
In index.js
import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>,
document.getElementById("root")
);
In App.js
import { Switch, Route, useLocation } from "react-router-dom";
import { AnimatePresence, motion } from "framer-motion";
function App() {
const location = useLocation();
return (
<AnimatePresence>
<Switch location={location} key={location.pathname}>
// all the routes here
</Switch>
</AnimatePresence>
);
}
Then in loading.js, surround the entire thing with a motion.div
. This motion.div
is what will animate. I've done a simple left to right for entering, and right to left for exit.
Changes made in loading.js
const routeTransition = {
hide: {
x: "100vw"
},
animate: {
x: 0,
transition: {
delay: 0.75,
duration: 0.75,
when: "beforeChildren",
staggerChildren: 0.5
}
},
exit: {
x: "-100vw",
transition: {
duration: 0.75
}
}
};
return (
<motion.div // this is the div that will animate the entire route
variants={routeTransition}
initial="hide"
animate="animate"
exit="exit"
>
<motion.div // this div will only animate the button
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={pagetransition}
className="loadingScreen"
>
<NavLink to="/sol">
<button>
<p>Enter System</p>
</button>
</NavLink>
</motion.div>
</motion.div>
);
Upvotes: 1