vue动画-实现购物车的动态添加动画

需求分析:进入产品列表,点击缩略图旁+号,有个该商品被动态添加到购物车的动画。让我们实现这个动画吧。

如下图:

通过动图可以发现移动的曲线是蜿蜒曲折的,这就用到了贝塞尔曲线。

他的弧度是这样的。
vue动画-实现购物车的动态添加动画_第1张图片

贝塞尔曲线链接

实现原理:先创建一个隐藏的圆点在购物车icon那里。当点击+号时,让圆点先移动到当前点击+的位置并让其显示。然后开始动画,让圆点移动回到原来的购物车icon位置并让其隐藏。

使用vue提供的vue动画和贝塞尔曲线来实现移动动画

vue动画详情链接

  1. HTML
<template>
   <div>
       <van-nav-bar
           title="图书战术"
           left-text="返回"
           left-arrow
           @click-left="onClickLeft"
       >
           <template #right>
               <van-icon name="cart-o" size="18" />
               <div class="shop_car_icon">{
    { shopCarNum }}div>
           template>
       van-nav-bar>
       <div class="bookmall__list">
           <ul>
               <li class="bookmall__item" v-for="(item, index) in testList" :key="index" @click="goBookUrl(item)">
                   <div class="bookmall__item-left">
                       {
    { item }}
                   div>
                   <div class="bookmall__item-right">
                       <h5>{
    { item }} <span>{
    { item }}span>h5>
                       <p><span>分类:span>{
    { item }}<span style="margin-left: 10px;padding: 10px;" class="shopCarAdd" @click.stop="addToShopCars"><van-icon name="add" color="rgb(238, 57, 57"/>span>p>
                       <p class="bookmall__item-right-tag"><span>标签:span>{
    { item }}p>
                       <p class="bookmall__item-right-sub2">
                           {
    { item }}
                       p>
                   div>
               li>
           ul>
       div>
       <transition
       @before-enter="beforeEnter"
       @enter="enter"
       @after-enter="afterEnter"
       >
           
           <div class="shop_car_ball" v-show="shopCarBall">
               <div class="linner_ball">
                   <van-icon name="add" color="rgb(238, 57, 57"/>
               div>
           div>
           
       transition>
   div>
template>
  1. CSS
.van-nav-bar {
     
   position: fixed;
   width: 100%;
}
.shop_car_icon {
     
   position: absolute;
   top: 10px;
   right: -8px;
   font-size: 10px;
   background-color: rgb(238, 57, 57);
   border-radius: 50%;
   text-align: center;
   color: rgb(82, 80, 80);
   line-height: 0;
   display: table-cell;
   vertical-align: middle;
   padding: 8px 2px;
}
.bookmall__list {
     
   padding-top: 40px;
   .bookmall__item {
     
       display: flex;
       padding: 10px;
       border-bottom: 1px a #000;
       .bookmall__item-left {
     
           flex: 25%;
           margin-right: 5px;
           img {
     
               width: 90px;
           }
       }
       .bookmall__item-right {
     
           flex: 75%;
           height: 130px;
           overflow: hidden;
           h5 {
     
               font-size: 16px;
               span {
     
                   margin-left: 65px;
                   font-weight: 400;
                   font-size: 12px;
                   color: rgb(107, 106, 106);
               }
           }
           p {
     
               font-size: 13px;
           }
           .bookmall__item-right-tag {
     
               color: rgb(119, 118, 118);
           }
           
       }
   }
}
.bookmall__item .bookmall__item-right-sub2 ::after {
     
   content: "...";
   position: absolute;
   right: 0;
   bottom: 0;
}

.shop_car_ball {
     
   position: fixed;
   top: 10px;
   right: 12px;
   z-index: 9;
   font-size: 16px;
   // transition: all .25s cubic-bezier(0.49, -0.29, 0.75, 90.41);
   /* 贝塞尔曲线 */
   transition: all .25s cubic-bezier(.17, .86, .73, .14);
   .linner_ball {
     
       transition: all .25s linear;
   }
}

  1. JS
export default {
     
   data () {
     
       return {
     
           shopCarNum: window.localStorage.getItem('shopcarnum') || 0,
           shopCarBall: false,
           shopCarBallEl: null,
           ss: null,
           // demo测试数据
           testList: new Array(1,2,3,4,5)
       }
   },
   methods: {
     
       addToShopCars (e) {
     
           this.shopCarBallEl = e.target
           this.shopCarBall = true
       },
       // 动画开始
       beforeEnter (el) {
     
       	   // 获取元素的大小及其相对于视口的位置
           const dom = this.shopCarBallEl.getBoundingClientRect()
           const offsetX = window.innerWidth - dom.left - 16
           const offsetY = dom.top - 22
   
           el.style.display = ''
           // y轴是曲直向上的,x轴是蜿蜒的向右的
           el.style.transform = `translate3d(0, ${
       offsetY}px, 0)`
           
           
           const linnerBall = el.querySelector('.linner_ball')
           linnerBall.style.transform = `translate3d(-${
       offsetX}px, 0, 0)`
       },
       enter (el, done) {
     
           // 触发重绘,来实现动画的移动过程
           this.ss = document.body.offsetHeight
           el.style.transform = `translate3d(0, 0, 0)`

           const linnerBall = el.querySelector('.linner_ball')
           linnerBall.style.transform = `translate3d(0, 0, 0)`
           el.addEventListener('transitionend', done)
       },
       afterEnter (el) {
     
           this.shopCarBall = false
           el.style.display = 'none'
           this.shopCarNum++
       }
   },
   watch: {
     
   	// 监听shopCarNum属性,只考虑新增。新增时储存本地做永久化处理
       shopCarNum (newValue) {
     
           window.localStorage.setItem('shopcarnum', newValue)
       }
   }
}

这样我们就实现购物车的动态添加demo。

你可能感兴趣的:(贝塞尔曲线,js,transition,前端,javascript,vue,vue动画,css3)