商品到购物车动画

<style type="text/css">

.ball {

  min-width: 15px;

  min-height: 15px;

  background-color: red;

  border-radius: 50%;

}

</style>

<template>

  <div id="app">

    <div class="btn" @click="drop($event)" v-for="(item, idx) in 6" :key="idx">

      加入购物车

    </div>

    <!-- 使用transition把元素小球包裹起来 -->

    <div class="flex_center">

      3252354353534534534523

      <div class="ball-container" style="position: relative">

        <div v-for="(ball, index) of balls" :key="index">

          <transition

            @before-enter="handleBeforeEnter"

            @enter="handleEnter"

            @after-enter="handleAfterEnter"

          >

            <div

              class="ball"

              :class="[`${'ball' + index}`]"

              style="position: fixed"

              v-show="ball.show"

              v-bind:css="false"

            >

              <!--外层盒子-->

              <div class="inner inner-hook"></div>

              <!--内层盒子-->

            </div>

          </transition>

        </div>

      </div>

    </div>

    <div class="flex_center">

      88888888888888888888888889999999999999

      <div class="ballTo" id="ballTo" style="position: relative">到这来</div>

    </div>

  </div>

</template>

<script type="text/javascript">

export default {

  data() {

    return {

      flag: false,

      balls: [

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

        { show: false, active: false },

      ],

      dropBalls: [], // 用dropBalls来存放掉落的小球

    };

  },

  methods: {

    drop(el) {

      for (let i = 0; i < this.balls.length; i++) {

        // 遍历这5个小球

        let ball = this.balls[i];

        if (!ball.show) {

          // 当小球显示状态为隐藏时

          ball.show = true; // 将这个小球的显示状态设置为true

          ball.active = true;

          ball.el = el; // 将cartControl传过来的对象挂载到ball的el属性上

          this.dropBalls.push(ball); // 将这个小球放入到dropBalls数组中

          // console.log(this.balls, 55);

          return;

        }

      }

    },

    handleBeforeEnter: function (el) {

      let count = this.balls.length;

      let box = document.getElementsByClassName("ball-container")[0];

      //   侧边栏位置

      let leftBar = document.getElementsByClassName("scrollbar")[0];

      //   顶部侧边栏

      let navbar = document.getElementsByClassName("navbar")[0];

      if (!(navbar && navbar.clientHeight)) {

        navbar = {

          clientHeight: 0,

        };

      }

      box.style.top = "100px";

      box.style.left = "100px";

      while (count--) {

        let ball = this.balls[count];

        if (ball.show && ball.active) {

          let x = 0,

            y = 0;

          x =

            ball.el.x -

            box.offsetLeft -

            leftBar.offsetWidth -

            leftBar.offsetLeft;

          y = (ball.el.y || 0) - box.offsetTop - navbar.clientHeight;

          //   let rect = ball.el.getBoundingClientRect(); // getBoundingClientRect()获取小球相对于视窗的位置,屏幕左上角坐标为0,0

          //   let x = rect.left - 32; // 小球x方向位移= 小球距离屏幕左侧的距离-外层盒子距离水平的距离

          //   let y = -(window.innerHeight - rect.top - 22); // 负数,因为是从左上角向下

          el.style.display = "";

          el.style.webkitTransform = `translate3d(${x}px,${y}px,0)`; // 设置外层盒子,即小球垂直方向的位移

          el.style.transform = `translate3d(${x}px,${y}px,0)`;

          // setTimeout(() => {

          //   el.style.transform = `translate3d(${x + 50}px,${y - 50}px,0)`;

          // }, 30);

          let inner = el.getElementsByClassName("inner-hook")[0];

          inner.style.webkitTransform = `translate3d(${x}px,${y}px,0)`; // 设置内层盒子,即小球水平方向的距离

          inner.style.transform = `translate3d(${x}px,${y}px,0)`;

        }

        ball.active = false; // 重置小球的active状态

      }

    },

    // enter

    handleEnter: function (el, done) {

      let box = document.getElementsByClassName("ball-container")[0];

      let ballTo = document.getElementById("ballTo");

      /* eslint-disable no-unused-vars */

      // 触发浏览器重绘

      let rf = el.offsetHeight;

      this.$nextTick(() => {

        let x = 200,

          y = -300,

          z = 0;

        y = ballTo.offsetTop - box.offsetTop;

        x = ballTo.offsetLeft - box.offsetLeft;

        // 让动画效果异步执行,提高性能

        el.style.webkitTransform = `translate3d(${x}px,${y}px,${z}px)`; // 设置小球掉落后最终的位置

        el.style.transform = `translate3d(${x}px,${y}px,${z}px)`;

        // el.style.animation = "drop 1s cubic-bezier(.1,-0.15,0,.42)";

        el.style.transition = "all 2s cubic-bezier(.49,-.29,.75,.41)";

        let inner = el.getElementsByClassName("inner-hook")[0];

        inner.style.webkitTransform = `translate3d(${x}px,${y}px,${z}px)`;

        inner.style.transform = `translate3d(${x}px,${y}px,${z}px)`;

        inner.style.transition = "all 2s cubic-bezier(.11,-.33,.55,.11)";

        el.addEventListener("transitionend", done); // Vue为了知道过渡的完成,必须设置相应的事件监听器。它可以是transitionend或 animationend

      });

    },

    handleAfterEnter: function (el) {

      let ball = this.dropBalls.shift(); // 完成一次动画就删除一个dropBalls的小球

      if (ball) {

        ball.show = false;

        el.style.display = "none";

      }

    },

  },

  mounted() {

    // setInterval(() => {

    //   this.drop({ x: Math.random(0, 1) * 700, y: Math.random(0, 1) * 900 });

    // }, 500);

  },

};

</script>

<style lang="less" scoped>

.btn {

  height: 80px;

}

.flex_center {

  display: flex;

  align-content: center;

}

</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值