vue-transition實現加入購物車效果及其他動畫效果實現

vue提供了<transition></transition>和<transition-group></transition-group>實現元素狀態的過渡.加入過渡效果可以使元素的展示和隱藏更自然.
如果在vue中使用了<transition></transition>標籤,vue會檢測是否有應用CSS過渡動畫或JavaScript鉤子函數,並在適當的階段添加添加/刪除類名和調用函數執行過渡動畫

在進入/離開的過渡中,會有 6 個 class 切換。

v-enter:定義進入過渡的開始狀態。在元素被插入之前生效,在元素被插入之後的下一幀移除。

v-enter-active:定義進入過渡生效時的狀態。在整個進入過渡的階段中應用,在元素被插入之前生效,在過渡/動畫完成之後移除。這個類可以被用來定義進入過渡的過程時間,延遲和曲線函數。

v-enter-to: 2.1.8版及以上 定義進入過渡的結束狀態。在元素被插入之後下一幀生效 (與此同時 v-enter 被移除),在過渡/動畫完成之後移除。

v-leave: 定義離開過渡的開始狀態。在離開過渡被觸發時立刻生效,下一幀被移除。

v-leave-active:定義離開過渡生效時的狀態。在整個離開過渡的階段中應用,在離開過渡被觸發時立刻生效,在過渡/動畫完成之後移除。這個類可以被用來定義離開過渡的過程時間,延遲和曲線函數。

v-leave-to: 2.1.8版及以上 定義離開過渡的結束狀態。在離開過渡被觸發之後下一幀生效 (與此同時 v-leave 被刪除),在過渡/動畫完成之後移除。
其他的概念性文字不贅述了,大家可以去官網查看

自己寫了幾個小例子,效果圖如下,這次的圖片轉換工具不行,GIF動圖沒弄好,大家勉強看看效果

下面貼代碼

./tansitionTest.vue
文字淡入淡出效果
<template>
  <div class="transition_test">
    <button @click="show = !show">click</button>
    // 頁面有多個transition時可以加name區分,如果沒有加name,默認CSS類名爲v-開頭
    <transition name="slide-fade">
      <div v-if="show" class="circle"></div>
    </transition>
    <div>
  </div>
</template>

export default {
    name: 'myTransition',
    components: {

    },
    data() {
      return {
        show: false
      }
    },
}

<style scoped>
  .transition_test {
    text-align: left;
    padding-bottom: 300px;
  }
  .circle {
    width: 100px;
    height: 100px;
    border-radius: 50%;
    background-color: aquamarine;
  }
.slide
-fade-enter-active, .slide-fade-leave-active { transition: all .5s ease-out; } .slide-fade-enter, .slide-fade-leave-to { /* transform: translateX(500px); */ opacity: 0; } </style>

 

加入購物車效果
場景:點擊添加按鈕,商品圖片展示,並移入到購物車位置,到購物車位置時隱藏商品圖片
<template>
  <div class="shop_cart">
    加入購物車動畫(css實現):
    <div class="add">
      <button @click="addShopCart">add</button>
      <transition name="shop_cart">
        <img class="add_img" v-if="addShow" src="../assets/voucher.png" alt="">
      </transition>
    </div>
    <div class="cart">
      <img src="../assets/cart.jpg" alt="">
    </div>
  </div>
</template>

export default {
    name: 'myTransition',
    components: {

    },
    data() {
      return {
        addShow: false
      }
    },
    methods: {
      addShopCart () {
        this.addShow = true
        // 添加類名的方法沒有動畫結束的時機,這裏我直接寫了一個定時器,時機和動畫時間一致,在圖片移動到購物車位置時隱藏
        setTimeout(() => {
          this.addShow = false
        }, 1000)
      }
    }
}

<style scoped>
  .transition_test {
    text-align: left;
    padding-bottom: 300px;
  }
  .shop_cart {
    padding: 20px;
  }
  .shop_cart .add {
    position: relative;
    margin-top: 100px;
    width: 500px;
    display: inline-block;
  }
  .shop_cart .add button {
    position: absolute;
    z-index: 99;
  }
  .shop_cart .cart{
    width: 300px;
    display: inline-block;
  }
  .shop_cart .cart img {
    width: 100%;
  }
  // 一開始調整好商品圖片在購物車的位置,移入效果最後顯示是在一開始定義好的位置
  .shop_cart .add_img {
    width: 100px;
    position: absolute;
    left: 600px;
    top: -160px;
  }
  // 可以有兩種方式實現飛入動畫,用動畫的效果感覺會更好一點
  /* 動畫效果實現 */
  /* @keyframes bounce-in {
    0% {
      transform: scale(1);
      transform: translate(-610px, 100px);
    }
    100% {
      transform: scale(.5);
      transform: translate(0px, 0px);
    }
  }
  .shop_cart-enter-active {
    animation: bounce-in 1s;
  } */

  /* CSS類名實現 */
  .shop_cart-enter-active {
    transition: all 1s ease-out;
  }
  .shop_cart-enter {
    opacity: 0;
    transform: scale(.5);
    transform: translate(-610px, 100px);
  }
</style>

 

其他效果不單獨放了,代碼放在一起,可以直接在vue項目中新建一個component,把代碼複製過去就可以使用了
<template>
  <div class="transition_test">
    <h2>   過渡效果</h2>

    <button @click="show = !show">click</button>
    <!-- <transition name="slide-fade">
      <div v-if="show" class="circle"></div>
    </transition> -->
    <div>
      圖片放大效果:
      <transition name="img-fade">
        <img class="bigimg" v-if="show" src="../assets/voucher.png" alt="">
      </transition>
    </div>
    <div class="shop_cart">
      加入購物車動畫(css實現):
      <div class="add">
        <button @click="addShopCart">add</button>
        <transition name="shop_cart">
          <img class="add_img" v-if="addShow" src="../assets/voucher.png" alt="">
        </transition>
      </div>
      <div class="cart">
        <img src="../assets/cart.jpg" alt="">
      </div>
    </div>

    <div class="shop_cart">
      加入購物車動畫(JavaScript鉤子函數實現):
      <div class="add">
        <button @click="addShopCart1">add</button>
        <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter">
          <img class="add_img_js" v-if="addShow1" src="../assets/voucher.png" alt="">
        </transition>
      </div>
      <div class="cart">
        <img src="../assets/cart.jpg" alt="">
      </div>
    </div>
    <!-- 動畫數組效果 -->
    <ul class="group_list">
      <button @click="addItem">addItem</button>
      <button @click="removeItem">removeItem</button>
      <transition-group name="list">
        <li class="group_item" v-for="item in list" :key="item">{{item}}</li>
      </transition-group>
    </ul>
  </div>
</template>
<script>
  export default {
    name: 'myTransition',
    components: {

    },
    data() {
      return {
        show: false,
        addShow: false,
        addShow1: false,
        list: [1, 2, 3]
      }
    },
    created() {

    },

    methods: {
      addShopCart () {
        this.addShow = true
        setTimeout(() => {
          this.addShow = false
        }, 1000)
      },
      addShopCart1 () {
        this.addShow1 = true
      },

      // 動畫鉤子函數
      // 進入前狀態
      beforeEnter (el) {
        el.style.left = '-20px'
        el.style.top = '-15px'
        el.style.transform = 'scale(1)'
      },
      // 進入中
      enter (el, done) {
        // 需要調用元素的offset操作,纔有過渡的效果,否則會馬上實現過渡
        el.offsetWidth
        el.style.left = '600px'
        el.style.top = '-160px'
        el.style.transform = 'scale(.5)'
        done()
      },
      // 進入後
      afterEnter () {
        this.addShow1 = false
      },

      // 新增
      addItem () {
        this.list.push(this.list.length + 1)
      },
      // 刪除
      removeItem () {
        if (this.list.length > 1) {
          this.list.pop()
        }
      }
    }

  }
</script>
<style scoped>
  .transition_test {
    text-align: left;
    padding-bottom: 300px;
  }
  .circle {
    width: 100px;
    height: 100px;
    border-radius: 50%;
    background-color: aquamarine;
  }
  .slide-fade-enter-active, .slide-fade-leave-active {
    transition: all .5s ease-out;
  }
  .slide-fade-enter, .slide-fade-leave-to {
    /* transform: translateX(500px); */
    opacity: 0;
  }
  .bigimg {
    width: 300px;
  }

  .img-fade-enter-active {
    transition: all 1s ease-out;
  }
  .img-fade-enter {
    transform: scale(.5);
    /* width: 50px; */
  }

  .shop_cart {
    padding: 20px;
  }
  .shop_cart .add {
    position: relative;
    margin-top: 100px;
    width: 500px;
    display: inline-block;
  }
  .shop_cart .add button {
    position: absolute;
    z-index: 99;
  }
  .shop_cart .cart{
    width: 300px;
    display: inline-block;
  }
  .shop_cart .cart img {
    width: 100%;
  }
  .shop_cart .add_img {
    width: 100px;
    position: absolute;
    left: 600px;
    top: -160px;
  }
  /* 動畫效果實現 */
  /* @keyframes bounce-in {
    0% {
      transform: scale(1);
      transform: translate(-610px, 100px);
    }
    100% {
      transform: scale(.5);
      transform: translate(0px, 0px);
    }
  }
  .shop_cart-enter-active {
    animation: bounce-in 1s;
  } */

  /* CSS類名實現 */
  .shop_cart-enter-active {
    transition: all 1s ease-out;
  }
  .shop_cart-enter {
    opacity: 0;
    transform: scale(.5);
    transform: translate(-610px, 100px);
  }
// JavaScript函數
  .shop_cart .add_img_js {
    width: 100px;
    position: absolute;
    left: 600px;
    top: -160px;
    transition: all 1s;
  }
// 動態列表
  .group_list {
    padding: 30px;
  }
  .group_list .group_item {
    width: 200px;
    height: 100px;
    border: 1px solid orangered;
    margin: 10px;
  }
  .list-enter-active, .list-leave-active {
    transition: all .8s;
  }
  .list-enter, .list-leave-to {
    opacity: 0;
    transform: translateX(40px);
  }
</style>