Takeshi Tokugawa YD
Takeshi Tokugawa YD

Reputation: 923

How to chain transitions/animation in Vue?

Target

enter image description here

On click "Open menu" button:

  1. Dim overlay appearing with fade-in animation

enter image description here

  1. Once dim overlay animation done, from the top, dim overlay is appearing with the sliding animation from the top to bottom:

enter image description here

Solution attempt and problem

<template lang="pug">
  transition(name="fade")
    .DrawerMenu-DimUnderlay(v-if="displayFlag")
      .DrawerMenu-Body Drawer menu
</template>

Before slide down the .DrawerMenu-Body, .DrawerMenu-DimUnderlay must be mounted and rendered. I don't know how to implement it.

enter image description here

🌎 Fiddle

Upvotes: 3

Views: 2197

Answers (2)

User 28
User 28

Reputation: 5158

You can achieve that by using CSS Animations and Vue Transition.

First, separate your overlay and content into different transitions:

<template lang="pug">
  div
    transition(name="overlay")
      .DrawerMenu-Overlay(v-if="displayFlag")
    transition(name="content")
      .DrawerMenu-Body(v-if="displayFlag") Drawer menu
</template>

Then define your animations:

.DrawerMenu {
  &-Overlay {
    ...
    display: none;
  }
  ...
}

.overlay-enter-active {
  display: block;
  animation: fade-in-and-slide-down 2s;
}

.content-enter-active {
  animation: wait-and-fade-in 3s;
}

.content-leave-active {
  animation: fade-out 1s;
}

@keyframes fade-in-and-slide-down {
  0% {
    opacity: 0;
  }

  50% {
    opacity: 1;
    transform: translateY(0);
  }

  100% {
    transform: translateY(100%);
  }
}

@keyframes wait-and-fade-in {
  0% {
    opacity: 0;
  }

  66% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

@keyframes fade-out {
  0% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

Example in CodeSandbox.

Another solution is using JavaScript animation library (such as animejs) combine with Vue Transition Hooks. I would prefer this solution for a complex animation.

<template lang="pug">
  transition(@enter='enter' @leave='leave')
    div(v-if='displayFlag')
      .DrawerMenu-Overlay(ref='overlay')
      .DrawerMenu-Body(ref='content' @click="displayFlag = false") Drawer menu
</template>
import anime from "animejs";
...
  methods: {
    enter(el, done) {
      anime
        .timeline({
          easing: "linear",
          duration: 1000,
          complete: done
        })
        .add({
          targets: this.$refs.overlay,
          opacity: [0, 1]
        })
        .add({
          targets: this.$refs.overlay,
          translateY: "100%"
        })
        .add({
          targets: this.$refs.content,
          opacity: [0, 1]
        });
    },
    leave(el, done) {
      anime({
        targets: el,
        duration: 2000,
        opacity: 0,
        complete: done
      });
    },
    ...
  }
...

You can also use without transition component but you have to handle v-if variable by yourself.

Example in CodeSandbox.

Upvotes: 2

CUGreen
CUGreen

Reputation: 3186

Not sure if there are 2 questions here, but for your last question, I would say that is because that ref component does not have a property display.

It does however, have a function display()

Therefore, change your button click to this:

<button @click="$refs.drawerMenu.display()">Open menu</button>

Upvotes: 0

Related Questions