vue 高仿饿了么 小球动画

<template>
  <div class="shopcart">
    <div class="content">
      <div class="content-left">
        <div class="logo-wrapper">
          <div class="logo" :class="{'highLight':totalCount > 0}">
            <i class="icon-shopping_cart" :class="{'highLight':totalCount > 0}"></i>
          </div>
          <div class="num" v-if="totalCount>0">{{totalCount}}</div>
        </div>
        <div class="price" :class="{'highLight':totalCount > 0}">¥{{totalPrice}}</div>
        <div class="desc"> 另需配送费¥ {{deliveryPrice}}元</div>
      </div>
      <div class="content-right">
        <div class="pay" :class="payClass">
          {{payDesc}}
        </div>
      </div>
    </div>
    <div class="ball-container">
      <transition-group name="drop" tag="div"
                        v-on:before-enter="beforeEnter"
                        v-on:enter="dropEnter"
                        v-on:after-enter="afterEnter"
      >
        <div class="ball" v-for="(ball,i) in balls" :key="i" v-show="ball.show">
         <div class="inner inner-hook"></div>
        </div>
      </transition-group>
    </div>
  </div>
</template>

<script type="text/ecmascript-6">
    export default {
        name: "shopcart",
        props:{
          selectFoods:{
            type:Array,
            default(){
              return [
                {
                  price:10,
                  count:5
                }
              ];
            }
          },
          deliveryPrice:{
            type: Number,
            default: 0
          },
          minPrice:{
            type: Number,
            default: 0
          },

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

            ],
            dropBalls:[]
          }
      },
      computed:{
        totalPrice(){
          let total = 0;
          this.selectFoods.forEach((food)=>{
            total+=food.price *  food.count
          });
          return total;
        },
        totalCount(){
          let count  = 0;
          this.selectFoods.forEach(food =>{
            count += food.count;
          });
          return count
        },
        payDesc(){
          if(this.totalPrice === 0){
            return ` ¥${this.minPrice}元起送`
          }else if(this.totalPrice<this.minPrice){
            return `还差${this.minPrice-this.totalPrice}元起送`
          }else{
            return '去结算'
          }
        },
        payClass(){
          if(this.totalPrice<this.minPrice)
            return 'not-enough';
          else
            return 'enough'
        }
      },
      methods:{
          drop(el){
            for(let i=0;i<this.balls.length;i++){
              let ball=this.balls[i];
              if(!ball.show){
                ball.show=true;
                ball.el=el;
                this.dropBalls.push(ball);
                return;
              }
            }
          },
        beforeEnter(el,done){

          let count = this.balls.length;
          while (count--){
            let ball = this.balls[count];
            if(ball.show){
              let rect = ball.el.getBoundingClientRect();
              let x=rect.left - 32;
              let y=-(window.innerHeight - rect.top -22);debugger
              el.style.display='';//显示
              el.style.webkitTransform=`translate3d(0,${y}px,0)`;
              el.style.transform=`translate3d(0,${y}px,0)`;
              let inner = el.getElementsByClassName('inner-hook')[0];
              inner.style.webkitTransform=`translate3d(${x}px,0,0)`;
              inner.style.transform=`translate3d(${x}px,0,0)`;

            }
          }
        },
        dropEnter(el,done){//球动画完成
            debugger
          /* eslint-disable no-unused-vars*/
          let rf = el.offsetHeight;
          this.$nextTick(()=>{
            el.style.webkitTransform='translate3d(0,0,0)';
            el.style.transform='translate3d(0,0,0)';
            let inner = el.getElementsByClassName('inner-hook')[0];
            inner.style.webkitTransform='translate3d(0,0,0)';
            inner.style.transform='translate3d(0,0,0)';
            el.addEventListener('transitionend', done);

          })

        },
        afterEnter(el){
            debugger
          el.style.display='none';
          let ball=this.dropBalls.shift();
          if(ball){
            ball.show=false;
            ball.el=null;
          }
            debugger

        }
      },
    }
</script>

<style lang="stylus" rel="stylesheet/stylus">
  .shopcart
    position: fixed
    left: 0
    bottom: 0
    z-index: 50
    width :100%
    height: 48px
    .content
      display: flex
      background: #141d27
      font-size: 0
      color: rgba(255,255,255,0.4)
      .content-left
        flex: 1
        .logo-wrapper
          display: inline-block
          position: relative
          top: -10px
          margin: 0 12px
          padding: 6px
          width: 56px
          height: 56px
          box-sizing: border-box
          vertical-align: top
          border-radius: 50%
          background: #141d27
          .logo
            width: 100%
            height: 100%
            border-radius: 50%
            background: #2b343c
            text-align: center
            &.highLight
              background: #00a0dc
            .icon-shopping_cart
              line-height: 44px
              font-size: 24px
              color: #80858a
              &.highLight
                color: white
          .num
             position: absolute
             top: 0
             right: 0
             width: 24px
             height: 16px
             line-height: 16px
             text-align: center
             border-radius: 16px
             font-size: 9px
             font-weight: 700
             color: #fff
             background: rgb(240,20,20)
             box-shadow: 0 4px 8px 0 rgba(0,0,0,0.4)

        .price
          display: inline-block
          vertical-align: top
          line-height: 24px
          margin-top: 12px
          padding-right: 12px
          box-sizing: border-box
          border-right: 1px solid rgba(255,255,255,0.1)
          font-size: 16px
          font-weight: 700
          &.highLight
            color: white

        .desc
          display: inline-block
          vertical-align: top;
          line-height: 24px
          margin: 12px 0 0 12px
          font-size: 10px
      .content-right
        flex: 0 0 105px
        width: 105px
        .pay
          height: 48px
          line-height: 48px
          text-align: center
          font-size: 12px
          font-weight: 700
          &.not-enough
            background: #2b333b
          &.enough
            background: #00b43c
            color: #fff




    .ball-container
      .ball
        position: fixed
        left: 32px
        bottom: 22px
        z-index: 200
        .inner
          width: 16px
          height: 16px
          border-radius: 50%
          background: rgb(0,160,220)
          transition: all 1s linear
        &.drop-enter-active
         transition: all 1s cubic-bezier(0.49,-0.29,0.75,0.41);

         /* &.drop-enter
            transform: translate3d(0,-400px,0)
            .inner
              transform: translate3d(300px,0,0)
          &.drop-enter-to
            transform: translate3d(0,0,0)
            .inner
              transform: translate3d(0,0,0)

*/
</style>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值