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>

 

posted @ 2019-05-31 09:41  潇湘羽西  阅读(9313)  评论(0编辑  收藏  举报