【CSS】不定区间进度条

效果

最近遇到了个需求,需要按后端传过来的刻度显示进度条,并且刻度个数不定,进度总额不定,要求进度会一直趋近于结尾但永远不会到达结尾。

实现

我的做法是只限于前90%显示后端传来的数据,后10%用来作趋近无穷的变化。

src/views/processLine.vue

<template>
  <div class="container">
      <div class="progressline">
        <div class="progress" v-for="(item, index) in list" :key="index" :style="progressDistance(item.perNode)"></div>
        <i class="line" :style="{ 'width': percent + '%'}"></i>
      </div>
      <div class="info">
        <p class="text2">{{title}}</p>
        <div class="node" v-for="(item, index) in list" :key="index" :style="nodeDistance(item.perNode)">{{item.node}}</div>
      </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  name: 'progressLine',
  computed: {
    ...mapGetters('task', ['myPercent', 'myList']),
    percent () {
      let len = this.myList.length
      return (90 / len) * this.myPercent
    }
  },
  data () {
    return {
    }
  },
  mounted () {
  },
  methods: {
    progressDistance (perNode) {
      let count = perNode + '%'
      return {left: `${count}`}
    },
    nodeDistance (perNode) {
      let count = perNode + '%'
      return {left: `calc(${count} - 60px)`}
    }
  }
}
</script>

<style lang="scss" scoped>
.text2 {
  font-size: 14px;
  line-height: 24px;
}
.node {
  color: rgba($color: #1C1F23, $alpha: 0.8);
}
.container {
  color: #1C1F23;
  .progressline {
    margin-top: 16px;
    position: relative;
    width: 100%;
    height: 8px;
    line-height: 8px;
    background-color: #FFF3D9;
    border-radius: 4px;
    overflow: hidden;
    text-align: center;
    .progress {
      position: absolute;
      width: 1px;
      background: rgba(89, 89, 89, 0.3);
      height: 8px;
      z-index: 9;
    }
    i {
      position: absolute;
      left: 0;
      top: 0;
      height: 100%;
      border-radius: 4px;
    }
    .line {
      background-image: linear-gradient(to right, #FFF026, #FFB200);
    }
  }
  .info {
    margin-top: 4px;
    position: relative;
    .node {
      position: absolute;
      width: 60px;
      font-size: 14px;
      text-align: right;
      top: 4px;
    }
  }
}
</style>

src/store/vuex.js

import Vue from 'vue'
import Vuex from 'vuex'
import task from './modules/task'

Vue.use(Vuex)

const locatVuexOption = {
  modules: {
    task
  }
}

export default new Vuex.Store(locatVuexOption)

src/store/task.js

import { getTaskInfo } from '@/api/task'
import { formatNum, formatThousand } from '@/common/utils'

const task = {
  namespaced: true,
  state: () => ({
	// 目前总数
    myCur: 0,
    // 任务阶梯列表
    myList: []
    // myList: [
    //   {
    //     class: 1,
    //     lowerNode: 1,
    //     reward: 2000        // 奖励/元
    //   },
    //   {
    //     class: 2,
    //     lowerNode: 4,
    //     reward: 12000        // 奖励/元
    //   },
    //   {
    //     class: 3,
    //     lowerNode: 8,
    //     reward: 30000        // 奖励/元
    //   },
    //   {
    //     class: 4,
    //     lowerNode: 16,
    //     reward: 80000        // 奖励/元
    //   },
    //   {
    //     class: 5,
    //     lowerNode: 25,
    //     reward: 120000        // 奖励/元
    //   }
    // ]
  }),
  getters: {
    // 任务进度
    myPercent: state => {
      const list = state.myList
      const cur = state.myCur
      const len = list.length
      let pastNum = 0
      let stage = 0
      let progress = 0
      for(let i = 0; i < len; i++) {
        if (cur >= list[i].lowerNode) {
          pastNum = list[i].lowerNode
          stage += 1
          if (i === len - 1) {
            if (cur == list[i].lowerNode) {
              return stage
            } else {
              // 不断重置上限
              let top = pastNum * (Math.ceil(cur/pastNum) + 1)
              progress = stage + ((cur - pastNum) / (top - pastNum))
            }
          }
          continue
        } else if (cur < list[i].lowerNode) {
          if (i === 0) {
            progress = stage + (cur / (list[i].lowerNode- pastNum))
          } else {
            progress = stage + ((cur - pastNum) / (list[i].lowerNode- pastNum))
          }
          break
        } else {
          break
        }
      }
      return progress
    },
    myList: state => {
      let res = []
      state.myList.forEach((item) => {
        let count = (90 / state.myList.length) * item.class
        let obj = {
          class: item.class,
          node: formatThousand(item.lowerNode),
          reward: formatNum(item.reward),
          perNode: count
        }
        res.push(obj)
      })
      return res
    }
  },
  mutations: {
    // 获取任务信息
    getMyTask (state, payload) {
      let data = JSON.parse(JSON.stringify(payload))
      state.myCur = data.cur
    },
    // 获取列表
    getMyList (state, payload) {
      state.myList = payload
    }
  },
  actions: {
    // 获取任务信息
    async getTaskInfoData ({ commit }, params) {
      const res = await getTaskInfo(params)
      if (res.data.status === 0) {
        commit('getMyTask', res.data.data.myTask)
        commit('getMyList', res.data.data.myList)
      } else {
        this._vm.$message.error(res.data.msg || '获取信息失败!')
      }
    }
  }
}

export default task

src/common/utils.js

//格式化数字(1,000,000.00)
export const formatNum = function (str) {
  let newStr = "";
  let count = 0;
  str += "";
  if (str.indexOf(".") == -1) {
    for (let i = str.length - 1; i >= 0; i--) {
      if (count % 3 == 0 && count != 0) {
        newStr = str.charAt(i) + "," + newStr;
      } else {
        newStr = str.charAt(i) + newStr;
      }
      count++;
    }
    str = newStr;
    return str;
  } else {
    for (let i = str.indexOf(".") - 1; i >= 0; i--) {
      if (count % 3 == 0 && count != 0) {
        newStr = str.charAt(i) + "," + newStr;
      } else {
        newStr = str.charAt(i) + newStr;
      }
      count++;
    }
    str = newStr + (str + "00").substr((str + "00").indexOf("."), 3);
    return str;
  }
}


// 格式化数字(10w)
export const formatThousand = function (str) {
  let num = Number(str)
  if(num < 10000) {
    return num.toString()
  } else {
    return Math.round(num / 10000).toString() + 'w'
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值