Chaining animations
Warning: These pages are from before the launch of Framer X22 and are about the older animation API. These animations might still work in the current version of Framer but are officially deprecated. Learn about the current animation API here.
You can attach animations to other animations and have them run consecutively with a bit of asynchronous JavaScript code.
Let’s say that I want a frame to animate down, and then back up. I might think of something like this:
export const MoveDownAndUpAgain: Override = () => {
return {
top: data.yPosition,
onTap() {
// Move down
animate(data.yPosition, 620);
// Move back up
animate(data.yPosition, 67);
}
};
};
Alas, that would have been too easy.
The two animations will start at the same time, and in this example, nothing will happen (because they cancel each other out).
To chain animations, you have to make one animation wait for the other, and that can only happen inside an asynchronous function.
But fortunately, we have a function that already contains our animations: onTap()
. We make it asynchronous by putting async
in front of it.
export const MoveDownAndUpAgain: Override = () => {
return {
top: data.yPosition,
async onTap() {
...
Then inside the function, you write await
before a statement that should be waited for, in this case: our first animation.
export const MoveDownAndUpAgain: Override = props => {
return {
top: data.yPosition,
async onTap() {
await animate(data.yPosition, 620).finished;
animate(data.yPosition, 67);
}
};
};
And that would (often) be enough, but because our statement is an animation we have to add .finished
at the end of the animate()
call.
Now the second animation will start when the first one completed.
Returning to the start position
I added one more detail: To always have the correct start position, I get the current top
from the frame’s props
and save I it in a variable called startPosition
.
And I animate back to startPosition
in the second animation.
export const MoveDownAndUpAgain: Override = props => {
data.yPosition.set(props.top);
const startPosition = props.top;
return {
top: data.yPosition,
async onTap() {
await animate(data.yPosition, 620).finished;
animate(data.yPosition, startPosition);
}
};
};
download this project