I have created an animation that takes a couple of seconds to play. The animation should only run when the element is in view, so I’ve used whileInView
. This works correctly, but when I scroll down (so the element is out of view), the animation seems to run backwards, because when I scroll up again, I can see that the animation does not start from the beginning but from the point that it reached when it ran backwards and when the element came into view again. I want the animation to run from the beginning instead.
I’ve created a small sandbox to demonstrate the issue:
https://codesandbox.io/s/dreamy-cache-mk2dq2?file=/src/App.js
import "./styles.css";
import { motion } from "framer-motion";
export default function App() {
return (
<div style={{ height: "1000px" }}>
<motion.div
id="box"
initial={{ x: 0 }}
whileInView={{ x: 300 }}
transition={{ duration: 5, ease: "linear" }}
>
<p>
The box should be moving now. Scroll down and then up again. The
animation will not instantly reset but run backwards.
</p>
</motion.div>
</div>
);
}
When you open the sandbox, the blue box will move. The animation takes 5 seconds. Scroll down and then up again (within five seconds). The animation will run from some point but not from the start.
How can I make the animation run from the start whenever the element comes into view?
2
Answers
p7dxb's answer gave me an idea. I found a very simple solution. You just have to set different transition values for
initial
andwhileInView
. Use a duration of 0 seconds forinitial
:Here's the new sandbox: https://codesandbox.io/s/objective-elgamal-p49wdq
I used
useInView
to track when the div was scrolled past withuseEffect
to be called when this changed. useInView referenceWhen its in view it runs your animation & when out of view does a quick reverse animation (maybe this second part can be done better but it works).
I also used
useAnimate
instead of the div definitions see more about useAnimate here.I edited the App.js on your codesandbox but don’t have an account to save and share a link. If you paste the below code in your sandbox’s App.js it should give you what you are after