小白超详细理解vue2.0 购物车之小球动效

 <div class="ball-container">
        <div v-for="(ball,index) in balls">
          <transition name="dropdown" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
            <div v-show="ball.show" :key="index" class="ball">
              <div class="inner inner-hook"></div>
            </div>
          </transition>
        </div>
      </div>

一.由于小球运动时x与y轴方向上的运动轨迹不同,因此一个小球需要两个div组成,外层控制y轴,内层控制x轴

 balls: [
          {show: false},
          {show: false},
          {show: false},
          {show: false},
          {show: false}
        ],

二.需要5个小球来完成动画,因为动画完成需要时间,如果再这个时间内多次触发,可能导致没有小球可以用,除非等前一个动画完成 。

   drop(el) {
        //触发一次事件就会将所有小球进行遍历
        for (let i = 0; i < this.balls.length; i++) {
          let ball = this.balls[i];
          if (!ball.show) { //将false的小球放到dropBalls
            ball.show = true;
            ball.el = el; //设置小球的el属性为一个dom对象
            this.dropBalls.push(ball);
            return;//此处return终结函数,这意味着每次触发事件,dropBalls内只增加一个ball
          }
        }
      },
  beforeEnter(el) { //这里的el指的是小球的Dom,与drop(el)参数区分开
        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); //计算出与小球初始位置垂直方向上的距离,y轴向上为负
            el.style.display = ''; //清空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-hook类来单纯被js操作
            inner.style.webkitTransform = `translate3d(${x}px,0,0)`;
            inner.style.transform = `translate3d(${x}px,0,0)`;
          }
        }
      },

      enter(el, done) {
        let rf = el.offsetHeight; //触发重绘html
        this.$nextTick(() => { //让动画效果异步执行,提高性能
          el.style.webkitTransform = 'translate3d(0,0,0)';
          el.style.transform = 'translate3d(0,0,0)';
          //处理内层动画
          let inner = el.getElementsByClassName('inner-hook')[0]; //使用inner-hook类来单纯被js操作
          inner.style.webkitTransform = 'translate3d(0,0,0)';
          inner.style.transform = 'translate3d(0,0,0)';
          el.addEventListener('transitionend', done); //Vue为了知道过渡的完成,否则无法进入到afterEnter中
        });
      },

      afterEnter(el) {
        let ball = this.dropBalls.shift(); //完成一次动画就删除一个dropBalls的小球,否则触发N次事件,dropBalls则有N个元素
        if (ball) {
          ball.show = false;
          el.style.display = 'none'; //隐藏小球
        }
      }
    },
      .ball
        position fixed
        left 32px
        bottom 22px
        z-index 1
        transition: all 0.4s cubic-bezier(0.49, -0.29, 0.75, 0.41)
        .inner
          width 16px
          height 16px
          border-radius 50%
          background rgb(0, 160, 220)
          transition  all 0.4s linear

对应的transition  .ball用贝塞尔曲线 ,

如果不是很明白为啥要设置多个小球,建议加长transition的动画时间,更有利于理解。

比如将动画设置为4s,在这个4s时间内触发6次,会发现第6次的小球没有马上弹出来,是因为此时this.balls中所有ball.show全为true,这样if内函数无法执行,v-show的值不变也不能触发动画。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值