• 【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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115

    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'
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
  • 相关阅读:
    第三部分—数据结构与算法基础_5. 排序算法
    随手记录用的笔记本,记录一些常见成语和古文
    【UART】UART Q&A
    RPC框架(一)——简易RPC
    自签名SSL证书的安全隐患和风险有哪些?
    DOM事件流+阻止冒泡事件+dom包含
    利用NVIDIA DALI读取视频帧
    多功能手持VH501TC采集仪如何处理监测数据
    使用“vue init mpvue/mpvue-quickstart“初始化mpvue项目时出现的错误及解决办法
    Dubbo-聊聊Dubbo协议
  • 原文地址:https://blog.csdn.net/Jessieeeeeee/article/details/126362037