记录一次基于VUE,类似“成长值”进度条的动画效果

142 阅读1分钟
记录一次基于VUE,类似“成长值”进度条的动画效果上代码:
注释:图片地址自行更换

//Progress组件
<template>
  <div class="wrap">
    <div class="wrap_text" ref="ref_item">
      <div
        :class="[index * 25 <= comp_value ? 'text_icon ti_active' : 'text_icon']"
        v-for="(item, index) in textarr"
        :key="index"
      >
        <div class="text">
          {{ item.text }}
        </div>
        <div class="icon">
          <img :src="item.img" alt="" />
          <span
            :class="[index * 25 <= comp_value ? 'circular ci_active' : 'circular']"
          ></span>
        </div>
        <div class="value">
          {{ item.value }}
        </div>
      </div>
    </div>

    <div
      class="wrap_line"
      :style="{ paddingLeft: paddwid + 'px', paddingRight: paddwid + 'px' }"
    >
      <div class="hei_line">
        <div class="hong_line" :style="{ width: comp_value + '%' }"></div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      textarr: [
        {
          text: "青铜",
          img: require("../../../../../../static/images/2021/01/mz.png"),
          value: "1",
        },
        {
          text: "白银",
          img: require("../../../../../../static/images/2021/01/tz.png"),
          value: "500",
        },
        {
          text: "黄金",
          img: require("../../../../../../static/images/2021/01/yz.png"),
          value: "1500",
        },
        {
          text: "铂金",
          img: require("../../../../../../static/images/2021/01/jz.png"),
          value: "3000",
        },
        {
          text: "钻石",
          img: require("../../../../../../static/images/2021/01/zz.png"),
          value: "5000",
        },
      ],
      paddwid: "",       //缩进的距离
      growth_value: 4000,//当前值
      comp_value: "",    //进度条的值
    };
  },
  mounted() {
    //获取节点数
    let children_num = this.$refs.ref_item.children.length;
    //计算缩进的距离
    this.paddwid = this.$refs.ref_item.children[0].offsetWidth / 2;

    let currentNode = 0; //创建的节点数
    let temp = 0;        //前一个节点值
    let overMoney = 0;   //当前值和前一个节点值的差值
    let redLine = 0;     //进度条的占比
    this.textarr.map((item) => {
      //根据当前值和遍历的节点值算出创建的节点数和前一个节点值
      if (parseInt(item.value) <= this.growth_value) {
        currentNode += 1;
        temp = parseInt(item.value);
      }
    });
    overMoney = this.growth_value - temp;
    /*计算进度条占比位置*/
    if (currentNode && currentNode > 0 && currentNode <= this.textarr.length) {
      if (currentNode == this.textarr.length) {
        redLine = 100;
      } else {
        redLine = (currentNode - 1) / (this.textarr.length - 1);
        redLine +=
          (overMoney /
            (this.textarr[currentNode].value - this.textarr[currentNode - 1].value)) *
          (1 / (this.textarr.length - 1));

        redLine = redLine * 100;
        redLine = redLine > 100 ? 100 : redLine;
        redLine = redLine < 0 ? 0 : redLine;
      }
    }

    /*进度条滑动特效*/
    let t = 1000;         //极限值
    let i = 0;            //步长
    let speedup = 20;     //速度
    let startspeed = 1;   //初始值
    let currentMoney = 0;
    var timer = setInterval(() => {
      if (i <= 500) {
        i += startspeed + (i / 500) * speedup;
      } else if (i > 500) {
        i += startspeed + speedup - +(((i - 500) / 500) * speedup);
      }
      currentMoney = parseInt((i * this.growth_value) / t);
      if (i >= t) {
        i = t;
        currentMoney = this.growth_value;
      }
      this.comp_value = redLine * (i / t);
      if (i >= t) {
        clearInterval(timer);
      }
    }, 16);
  },
};
</script>

<style scope>
.wrap {
  margin-top: 0.54rem;
  margin-bottom: 0.455rem;
  width: 100%;
  height: 1.28rem;
  position: relative;
}
.wrap_text {
  box-sizing: border-box;
  width: 100%;
  opacity: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}
.text_icon {
  display: flex;
  flex-direction: column;
  flex: 1;
  font-family: PingFangSC-Regular;
  font-size: 0.24rem;
  color: rgba(2, 0, 0, 0.6);
  letter-spacing: 0;
  text-align: center;
  line-height: 0.24rem;
}
.ti_active {
  color: #020000;
}
.icon {
  text-align: center;
  margin: 0.11rem 0 0.29rem 0;
}
.icon .circular {
  position: absolute;
  top: 0.85rem;
  z-index: 15;
  display: inline-block;
  background: #e4ebf1;
  width: 0.08rem;
  height: 0.08rem;
  border-radius: 0.04rem;
}
.icon .ci_active {
  background: #ff3a1e;
}
.icon img {
  width: 0.4rem;
  height: 0.4rem;
  margin-left: 0.565rem;
}
.wrap_line {
  width: 100%;
  height: 0.04rem;
  box-sizing: border-box;
  position: absolute;
  top: 0.87rem;
}
.wrap_line .hei_line {
  width: 100%;
  height: 0.04rem;
  background: #e4ebf1;
  border-radius: 0.02rem;
}
.wrap_line .hei_line .hong_line {
  height: 0.04rem;
  background: #ff3a1e;
  border-radius: 0.02rem;
}
</style>