vue+H5模仿支付宝收能量效果

303 阅读1分钟

先上案例图片:

3.png 需求按照每组n个(这里是每组5个)数量展示。点击能量球的时候能量球下落触发接口。 上代码: template模块

<template>
  <div class="collectHome">
    <img
      :class="['tree', moveEnd ? 'flip' : '']"
      src="@/assets/images/tree2.png"
      alt=""
    />
    <div class="bubbles-box">
      <div
        class="bubble-card"
        v-for="(item, index) in bubbleList"
        :class="'bubble' + index"
        @click="collect(item, index)"
        v-show="!item.show"
        :key="index"
      >
		<div class="bubble-self">
			
		</div>
        <div class="bubble-label">{{ item.name }}</div>
        <div class="bubble-num">+{{ item.value }}</div>
      </div>
      <div
        class="bubble-card hidden"
        v-for="(m, n) in bubbleList"
        :class="m.show ? 'mv' + n : ''"
        :key="'key' + n"
      >
       
		<div class="bubble-self">
			
		</div>
        <div class="bubble-num">+{{ m.value }}</div>
      </div>
    </div>
  </div>
</template>`

js模块:

<script>

export default {
  data() {
    return {
      resdata: [
        // 全部待收取
        {
          id: 0,
          num: 1,
        },
        {
          id: 1,
          num: 2,
        },
        {
          id: 2,
          num: 3,
        },
        {
          id: 3,
          num: 4,
        },
        {
          id: 4,
          num: 5,
        },
        {
          id: 5,
          num: 6,
        },
        {
          id: 6,
          num: 7,
        },
        {
          id: 7,
          num: 8,
        },
        {
          id: 8,
          num: 9,
        },
        {
          id: 9,
          num: 10,
        },
        {
          id: 10,
          num: 11,
        },
        {
          id: 11,
          num: 12,
        },
        {
          id: 12,
          num: 13,
        },
      ],
      bubbleList: [], // 页面展示待收取
      moveEnd: false, // 移动结束状态,用于触发树的动画
      pagination: {
        page: 1,
        pageSize: 5,
        totalPage: 0,
      },
    };
  },
  watch: {
  },
  mounted() {this.getBubbleList()},
  methods: {
    collect(item, index) {
      this.bubbleList[index].show = true;
      console.log(item, "这是点击的数据");
      // !给树加个动画
      this.moveEnd = true;
      setTimeout(() => {
        this.moveEnd = false;
      }, 900);
      // !树动画结束
      // !这里可以放后台接口每点击一次调用收能量的接口
			console.log(item)
      //   若当前悬浮能量收集完毕,则跳下一页,并赋予下一页能量数量
      console.log(this.bubbleList.filter((item) => item.show == false));
      if (this.bubbleList.filter((item) => item.show == false).length == 0) {
        if (this.pagination.page == this.pagination.totalPage) {
          return;
        }
        this.pagination.page++;
        // 给个定时器,不然一组的最后一个的动画动不了
        setTimeout(() => {
          this.bubbleList = this.EnergyList.slice(
            (this.pagination.page - 1) * this.pagination.pageSize,
            this.pagination.page * this.pagination.pageSize
          );
          console.log(this.bubbleList);
        }, 1000);
      }
    },
    getBubbleList() {
		// 这里可以放接口一开始查询能量有多少个。然后根据需求(我这里是5个)一组展示。一组收完再展示另一组。
		this.pagination.totalPage = Math.ceil(
		this.resdata.length / this.pagination.pageSize
		);
		this.EnergyList = this.resdata.map((k) => {
		return {
			id: k.id,
			name: "能量",
			value: k.num,
			show: false,
			};
		});
		this.bubbleList = 
		this.EnergyList.slice(0, this.pagination.pageSize);
		
    },

  },
};
</script>

样式模块:

<style lang="less" scoped>
.collectHome {
  width: 100%;
  // background: #fee5bb;
  padding-top: 100px;
  position: relative;

  .tree_bg {
    height: 238px;
    width: 100%;
    position: absolute;
    top: 370px;
    z-index: 20;
  }
  .bottom-bg {
    width: 100%;
    position: absolute;
    bottom: -170px;
  }
  .tree {
    margin: 0 75px;
    width: calc(100% - 150px);
    object-fit: contain;
    position: relative;
    z-index: 30;
  }
  .bubbles-box {
    width: 100%;
    height: 120px;
    position: absolute;
    top: 0;
    left: 0;
    .bubble-card {
      width: 52px;
      position: absolute;
      text-align: center;
      font-size: 0;
      .bubble-self {
		height: 52px;
		border-radius: 100%;
        width: 100%;
        object-fit: contain;
		background: linear-gradient(0deg, #d5efa0 0%, #8fb675 100%);
      }
      .bubble-label {
        width: 100%;
        font-size: 12px;
        transform: scale(0.8);
        -webkit-transform: scale(0.8);
        font-weight: 400;
        color: #feae0f;
      }
      .bubble-num {
        font-size: 13px;
        font-weight: 400;
        color: #feae0f;
        position: absolute;
        top: 32px;
        left: 50%;
        transform: translateX(-50%);
        -webkit-transform: translateX(-50%);
      }
    }
    .mv0 {
      display: block;
      animation: move0 2s linear forwards;
      -webkit-animation: move0 2s linear forwards;
    }
    .mv1 {
      display: block;
      animation: move1 2s linear forwards;
      -webkit-animation: move1 2s linear forwards;
    }
    .mv2 {
      display: block;
      animation: move2 2s linear forwards;
      -webkit-animation: move2 2s linear forwards;
    }
    .mv3 {
      display: block;
      animation: move3 2s linear forwards;
      -webkit-animation: move3 2s linear forwards;
    }
    .mv4 {
      display: block;
      animation: move4 2s linear forwards;
      -webkit-animation: move4 2s linear forwards;
    }
  }
  .bubble0 {
    left: 25px;
    top: 90px;
  }
  .bubble1 {
    left: 80px;
    top: 40px;
  }
  .bubble2 {
    left: calc(50% - 26px);
    top: 20px;
  }
  .bubble3 {
    right: 80px;
    top: 40px;
  }
  .bubble4 {
    right: 25px;
    top: 90px;
  }
  @keyframes move0 {
    0% {
      left: 25px;
      top: 90px;
      width: 52px;
    }
    25% {
      left: calc(50% - 40px);
      top: 200px;
      width: 35px;
    }
    100% {
      left: calc(50% - 26px);
      top: 380px;
      width: 20px;
      opacity: 0;
    }
  }
  @keyframes move1 {
    0% {
      left: 80px;
      top: 40px;
      width: 52px;
    }
    25% {
      left: calc(50% - 40px);
      top: 200px;
      width: 35px;
    }
    100% {
      left: calc(50% - 26px);
      top: 380px;
      width: 20px;
      opacity: 0;
    }
  }
  @keyframes move2 {
    0% {
      left: calc(50% - 26px);
      top: 20px;
      width: 52px;
    }
    100% {
      left: calc(50% - 26px);
      top: 380px;
      width: 20px;
      opacity: 0;
    }
  }
  @keyframes move3 {
    0% {
      right: 80px;
      top: 40px;
      width: 52px;
    }
    25% {
      right: calc(50% - 40px);
      top: 200px;
      width: 35px;
    }
    100% {
      right: calc(50% - 26px);
      top: 380px;
      width: 20px;
      opacity: 0;
    }
  }
  @keyframes move4 {
    0% {
      right: 25px;
      top: 90px;
      width: 52px;
    }
    25% {
      right: calc(50% - 40px);
      top: 200px;
      width: 35px;
    }
    100% {
      right: calc(50% - 26px);
      top: 380px;
      width: 20px;
      opacity: 0;
    }
  }

  .hidden {
    display: none;
  }
  // 触发树的动画flip
  .off {
    animation: 1s seconddiv;
    -webkit-animation: 1s seconddiv;
    background: transparent;
  }

  @keyframes seconddiv {
    0% {
      transform: scale(1.4, 1.4);
    }
    10% {
      transform: scale(1, 1);
    }
    25% {
      transform: scale(1.2, 1.2);
    }
    50% {
      transform: scale(1, 1);
    }
    70% {
      transform: scale(1.2, 1.2);
    }
    100% {
      transform: scale(1, 1);
    }
  }
  .flip {
    animation: treeFlip 0.7s ease-in-out;
  }
  @keyframes treeFlip {
    from {
      transform: scale3d(1, 1, 1);
    }
    25% {
      transform: scale3d(1, 1.05, 1);
    }
    50% {
      transform: scale3d(1, 0.95, 1);
    }
    75% {
      transform: scale3d(1, 1.05, 1);
    }
    to {
      transform: scale3d(1, 1, 1);
    }
  }
}
</style>

小伙伴们根据自己的需求稍微改动一下应该就可以了。有些地方可以优化。欢迎大佬指点