Framer » Archive » Animations (pre X22) » Delaying an animation

Delaying an animation

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.

Say we want the use this same ‘move down, then back up’ animation as in Chaining animations, but with a slight pause between the two movements.

There are two ways to do this, you use JavaScript’s setTimeout() function, or you insert a fake, dummy animation between the two real animations.

Using setTimeout()

The more official way would be to use JavaScript’s setTimeout() method.

You give setTimeout() a function, with inside it everything that should happen after the delay, plus a duration for that delay.

So it actually only takes two parameters:

setTimeout(«a_function», «a_delay_in_milliseconds»);

Below I give if an arrow function. The function doesn’t need to have a name, so it looks like this:

() => {
  animate(data.yPositionLeftBlock, startPosition);
}

… and then the delay: 1500.

export const DelayedAnimation_1: Override = props => {
  data.yPositionLeftBlock.set(props.top);
  const startPosition = props.top;
  return {
    top: data.yPositionLeftBlock,
    onTap() {
      animate(data.yPositionLeftBlock, 645).finished;
      setTimeout(() => {
        animate(data.yPositionLeftBlock, startPosition);
      }, 1500);
    }
  };
};
download this project

The animations didn’t get any specified duration, so they’ll have the default length of 1 second: 1000 milliseconds. So with this delay of 1500 milliseconds, the second animation will start half a second after the first one.

Using a dummy animation

This is a neat trick.

You just create an extra Animatable that is not connected to any property (here: dummy), and you animate it, with the duration that you want the delay to be (here: 0.5).

export const DelayedAnimation_2: Override = props => {
  data.yPositionRightBlock.set(props.top);
  const startPosition = props.top;
  return {
    top: data.yPositionRightBlock,
    async onTap() {
      await animate(data.yPositionRightBlock, 645).finished;
      const dummy = Animatable(0);
      await animate.ease(dummy, 1, { duration: 0.5 }).finished;
      animate(data.yPositionRightBlock, startPosition);
    }
  };
};

By using async / await / finished (like we did in Chaining animations), you then let the animations wait for each other.

(By the way, here I’m animating from 0 to 1, but you can use any values, and the name also doesn’t have to be dummy.)

This can be a bit shorter. You actually don’t need to create a variable (dummy) for the Animatable. You can just write Animatable inline because you don’t need to refer to it anywhere else.

export const DelayedAnimation_2: Override = props => {
  data.yPositionRightBlock.set(props.top);
  const startPosition = props.top;
  return {
    top: data.yPositionRightBlock,
    async onTap() {
      await animate(data.yPositionRightBlock, 645).finished;
      await animate.ease(Animatable(0), 1, { duration: 0.5 }).finished;
      animate(data.yPositionRightBlock, startPosition);
    }
  };
};
download this project