Vue3 real life transitions and microinteractions

Vue provides a simple and elegant way to handle animations. We can  <transition /> easily apply them by adding a directive that does all the heavy lifting for us. Alternatively, you can leverage javascript hooks to incorporate more complex logic into your animations, and even add gsapthird-party libraries like this one for more advanced usage scenarios.

In this post, we'll explore these different options, but first, let's put Vue aside for a moment and talk about the difference between CSS transitions and animations.

Transition Effects Vs Animation Effects

Transitions are made between two different states. start state and end state. Just like modal components, the start state may be hidden and the end state may be visible. With these states set, the browser fills in this state change with a series of intermediate frames.

 
 

button { background-color: #0ff1ce; transition: background-color 0.3s ease-in; } button:hover { background-color: #c0ffee; }

If you want to perform something that doesn't explicitly involve a start state and an end state, or if you need more fine-grained control over the keyframes in the transition, then you have to use animation.

If you want to perform something that doesn't explicitly involve a start state and an end state, or if you need more fine-grained control over the keyframes in the transition, then you have to use  animation .

 
 

button:hover { animation-duration: 3s; animation-iteration-count: infinite; animation-name: wobble; } @keyframes wobble { 0%, 100% { transform: translateX(0%); transform-origin: 50% 50%; } 15% { transform: translateX(-32px) rotate(-6deg); } 30% { transform: translateX(16px) rotate(6deg); } 45% { transform: translateX(-16px) rotate(-3.6deg); } 60% { transform: translateX(10px) rotate(2.4deg); } 75% { transform: translateX(-8px) rotate(-1.2deg); } }

will result in the following:

2541474772-641fa70ec792f.webp

If you consider that many properties can be animated, that multiple animations can be applied to an element, and that they can be controlled using javascript, the animation possibilities are endless.

Vue.js transition directive

In Vue.js projects, we can easily use transitions and animations by using the built-in transition directives. During the animation, Vue will add the appropriate class to the enclosing element.

image.png

Transition Classes

Enter

  • v-enter-from : initial state.
  • v-enter-active : Active state. Applied throughout animation stages.
  • v-enter-to : End state.

leave

  • v-leave-from : initial state.
  • v-leave-active : Active state of leave. Applied throughout the animation stage.
  • v-leave-to : End state.

In the case of named transitions, the name will replace  v- the prefix.

At first, it was a bit confusing for me, but as we dig into the code, everything becomes easier to understand. Let's start with an example.

animation example

Some trivial parts of the markup are omitted for brevity, but everything including a live demo is available on github.

Toggle with fade animation

1716770905-641fa80a7d52b.webp

 
 

<button @click="toggle">Toggle</button> <transition name="fade"> <div class="box" v-if="!isHidden"></div> </transition>

 
 

.fade-enter-active, .fade-leave-active { transition: opacity 0.3s; } .fade-enter-from, .fade-leave-to { opacity: 0; }

Toggle with sliding animation

3880566585-641fa8a5f0c1a.webp

 
 

.slide-enter-active { transition-duration: 0.3s; transition-timing-function: ease-in; } .slide-leave-active { transition-duration: 0.3s; transition-timing-function: cubic-bezier(0, 1, 0.5, 1); } .slide-enter-to, .slide-leave-from { overflow: hidden; } .slide-enter-from, .slide-leave-to { overflow: hidden; height: 0; }

switch between two buttons

1252280697-641faab03d88c.webp

 
 

<transition name="fade" mode="out-in"> <button @click="toggle" v-if="!isHidden" key="first">First State</button> <button @click="toggle" v-else key="second">Second State</button> </transition>

 
 

.fade-enter-active, .fade-leave-active { transition: opacity 0.3s; } .fade-enter-from, .fade-leave-to { opacity: 0; }

Toggle between two states

4020400895-641faaebd8d81.webp

 
 

.bounce-enter-active { animation: bounce 0.3s; } .bounce-leave-active { animation: bounce 0.3s reverse; } @keyframes bounce { 0% { transform: scale(1); opacity: 0; } 60% { transform: scale(1.1); } 100% { transform: scale(1); opacity: 1; } }

List addition, deletion and shuffling

609256634-641fab237b924.webp

 
 

.list-enter-active, .list-leave-active { transition: all 0.3s; } .list-enter-from, .list-leave-to { opacity: 0; transform: scale(0); } /* Shuffle */ .list-move { transition: transform 0.6s; }

Modal mode

1119324490-641fab4d1ba8e.webp

 
 

.modal-enter-from { opacity: 0; } .modal-leave-active { opacity: 0; } .modal-enter-from .modal-container, .modal-leave-active .modal-container { -webkit-transform: scale(1.1); transform: scale(1.1); }

card animation

2556958961-641fab836d370.webp

 
 

/* moving */ .slideLeft-move { transition: all 0.6s ease-in-out 0.05s; } /* appearing */ .slideLeft-enter-active { transition: all 0.4s ease-out; } /* disappearing */ .slideLeft-leave-active { transition: all 0.2s ease-in; position: absolute; z-index: 0; } /* appear at / disappear to */ .slideLeft-enter-from, .slideLeft-leave-to { opacity: 0; }

Expand/collapse animation

1688147364-641faba80d402.webp

 
 

.list-enter-active, .list-leave-active { transition: all 0.5s; } .list-enter-from, .list-leave-to { opacity: 0; height: 0; }

progress animation

385601764-641fabd3b3467.webp

 
 

<div class="progress-steps"> <div class="progress"> <div class="percent" :style="{width: `${ (progress-1) * 30 }%`}"></div> </div> <div class="steps"> <div class="step" v-for="index in 4" @click="setProgress(index)" :key="index" :class="{'selected': progress === index, 'completed': progress > index }"></div> </div> </div>

 
 

.container { position: relative; margin-top: 100px; } .progress-steps { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .steps { position: relative; display: flex; justify-content: space-between; width: 200px; } .step { width: 20px; height: 20px; background: #ffffff; border: 2px solid lightgray; border-radius: 50%; transition: all 0.6s; cursor: pointer; } .step.selected { border: 2px solid #42b983; } .step.completed { border: 2px solid #42b983; background: #42b983; border-radius: inherit; } .step.completed:before { font-family: "FontAwesome"; color: white; content: "\f00c"; } .progress { position: absolute; width: 100%; height: 50%; border-bottom: 2px solid lightgray; z-index: -1; } .percent { position: absolute; width: 0; height: 100%; border-bottom: 2px solid #42b983; z-index: 1; transition: width 0.6s; }

navigation animation

2063619372-641fac086486a.webp

 
 

... methods: { navigateTo(item) { const previousItem = this.$refs[`Item_${this.currentRoute.id}`]; const nextItem = this.$refs[`Item_${item.id}`]; this.currentRoute = item; this.animateOut(previousItem); this.animateIn(nextItem); }, animateIn(item) { this.tweenColor(item, { backgroundColor: this.currentRoute.color, color: "white" }); this.tweenSize(item, 64); }, animateOut(item) { this.tweenColor(item, { backgroundColor: "white", color: "gray" }); this.tweenSize(item, 32); }, tweenColor(item, options) { TweenMax.to(item, 0.3, options); }, tweenSize(item, width) { TweenMax.to(item, 0.7, { width, ease: Elastic.easeOut.config(1, 0.5) }); } } ...

Differences from Vue 2

Animations are one of many features affected by the Vue 3 migration. The migration build doesn't report this as a breaking change, which can be confusing.

The old class looked like this:

image.png

As you can see,  the .v-enter and  .v-leave classes are now replaced by  .v-enter-from and  .v-leave-from . Also, the transition element property that controls the animation class name has   changed  from enter-class and  to  and   .leave-classenter-class-fromleave-class-from

Vue provides a powerful way to incorporate simple or complex animations into our applications. When used correctly, they can enhance the overall user experience and make the interface more natural and professional. However, there is always a balance to be found, as too much animation can have the opposite effect. So, make sure not to overdo it.

Guess you like

Origin blog.csdn.net/m0_60961651/article/details/132576538