Viết animation cho Vue Component

Vue có sẵn một component để chuyên làm animation là <transition/>

<transition>
  <component />
</transition>

Nó sẽ thêm một số CSS class, mà dựa vào đó chúng ta có thể thêm animation cho component.

  • v-enter: state ban đầu, được thêm vào trước khi element được chèn vào DOM, remove ngay sau frame insert
  • v-enter-active: được thêm vào trước lúc insert remove sau khi animation kết thúc, tồn tại trong suốt lúc enter. Có thể dùng để define duration, delay, easing cho transition enter
  • v-enter-to: có từ version 2.1.8. Add sau 1 frame khi element đã insert, cùng lúc với v-enter bị xóa, xóa sau khi animation kết thúc.
  • v-leave: thêm vào ngay lúc có transition leaving, remove sau đó 1 frame
  • v-leave-active: sẽ có trong lúc leaving. Tương tự v-enter-active
  • v-leave-to: tương tự v-enter-to

Làm animation trong Vue bằng component transition

Nếu không thích thêm v- vào trước mấy class này, chúng ta có thể define một cái prefix khác.

<transition name='my-transition' />

Để thêm giá trị duration trên component (tính theo mili giây)

<transition :duration="1000" />
<transition :duration="{ enter: 500, leave: 800 }"/>

Ví dụ 1: làm dropdown menu

<li class="dropdown">
  <button class="dropbtn" @mouseover="show = true" @mouseout="show = false">Dropdown 
    <i class="down-arrow"></i>
  </button>
  <transition name="dropdown">
    <ul class="dropdown-content" v-if="show" @mouseover="show = true" @mouseout="show = false">
      <li><a href="#">Link 1</a></li>
      <li><a href="#">Link 2</a></li>
      <li><a href="#">Link 3</a></li>
   </ul>
 </transition>
</li> 

Thêm các CSS cần thiết

.dropdown-enter,
.dropdown-leave-to {
  transform: scaleY(0.7);
  opacity: 0;
}
.dropdown-enter-to,
.dropdown-leave {
  opacity: 1;
  transform: scaleY(1);
} 
.dropdown-enter-active,
.dropdown-leave-active {
  transition: all 0.3s ease-out;
  transform-origin: top center;
}

Ví dụ 2: làm form flipping

<transition name="card" mode="out-in">
  <div class="card" v-if="front == true" key="front">
    <h2>Sign In</h2>
    <div class="form">
      <h1>Sign In Form</h1>
    </div>
    <div class="footer">
      <span>Not a member?</span>
      <button @click="front = false">
        Join Us
      </button>
    </div>
  </div>
  <div class="card" v-else key="back">
    <h2>Sign Up</h2>
    <div class="form">
      <h1>Sign Up Form</h1>
    </div>
    <div class="footer">
      <span>Already a member?</span>
      <button @click="front = true">
        Log In
      </button>
    </div>
  </div>
</transition>

CSS cần thiết

.card-enter, .card-leave-to {
  opacity: 0;
  transform: rotateY(90deg);
} 
.card-enter-active, .card-leave-active {
  transition: all 0.5s;
}

See the Pen Vue Case 2: Flipping Form by Envato Tuts+ (@tutsplus) on CodePen.

Ví dụ 3: modal

HTML

<div id="app">
  <div v-bind:class="[isShowing ? blurClass : '', clearClass]">
    <p>Lorem ipsum dolor sit amet...</p>
    <button @click="toggleShow">Say Hello</button>
  </div>
  <transition enter-active-class="animated zoomIn"
    leave-active-class="animated zoomOut">
    <modal v-if="isShowing" class="modal">
      <button @click="toggleShow">Close</button>
    </modal>
  </transition>
</div>

CSS

.clear {
  transition: opacity 1s;
} 
.blur {
  filter: blur(1px);
  opacity: 0.5;
}

Ví dụ 4: Todo list

<div>
  <input v-model="newItemText" />
  <button v-on:click="addNewTodo">Add</button>
  <button v-on:click="removeTodo">Remove</button>
  <transition-group name="list" tag="ul">
    <li v-for="task in tasks" v-bind:key="task" >{{ task }}</li>
  </transition-group>
</div>

CSS

.list-enter-active {
  animation: add-item 1s;
} 
.list-leave-active {
  position: absolute;
  animation: add-item 1s reverse;
} 
.list-move {
  transition: transform 1s;
}
@keyframes add-item {
  0% {
    opacity: 0;
    transform: translateX(150px);
  }
  50% {
    opacity: 0.5;
    transform: translateX(-10px) skewX(20deg);
  }
  100% {
    opacity: 1;
    transform: translateX(0px);
  }
}

Phần code ví dụ lấy từ Tutsplus