I have a component that's inside a Framer Motion div. That component has a CSS animation, but the timing for the animation is off, because the Framer Motion animation takes a variable amount of time to complete.
What I'd like is someway to tell Framer Motion "do your animation, but then tell me when you are done, so I can trigger my other animation". Is that possible?
The code for the Framer Motion element is:
<motion.section
initial={{ x: 100, opacity: 0 }}
animate={{ x: 0, opacity: 1 }}
transition={{ when: 'beforeChildren'}}
>
<MyComponent/>
</motion.section>
MyComponent
has its own CSS animation, triggered with a useEffect
and some DOM manipulation to add a class:
const MyComponent = () => {
useEffect(() =>{
const id = getFromUrl();
document.getElementById(id).classList.add('animation-class');
}, [])
// ... rest of component ...
}
Here's the CSS for the animation:
.purple-highlight {
animation: glow 5s infinite alternate;
animation-iteration-count: 1;
animation-timing-function: linear;
}
@keyframes glow {
0% {
box-shadow: 8px 0 5px 1px var(--purple-500);
}
100% {
box-shadow: 0 0 0 0 var(--purple-500);
}
}
The problem is, the 5s
in the animation CSS is either too short or too long. If the Framer Motion stuff takes awhile, the CSS animation finishes before it even becomes visible ... but if I set it to 20s
then when Framer finishes more quickly, the animation lasts too long.
Hopefully there's some way to trigger code after Framer Motion is done with its animation?
Framer Motion adds some animation events to each motion
element. You can add the onAnimationComplete
prop to your motion element that will run when each animation is complete.
<motion.section
initial={{ x: 100, opacity: 0 }}
animate={{ x: 0, opacity: 1 }}
transition={{ when: 'beforeChildren'}}
onAnimationComplete={() => alert('Animation Complete!')}
>
<MyComponent/>
</motion.section>
Here is a working example.