加載進度條demo

<template>
  <div class="progress-box">
    <div class="container">
      <div class="loading-icon" ></div>
      <div class="loading-bar">
        <div class="progress" :style="{ width: process + '%'}"></div>
      </div>
      <div class="loading-text">{{ `${Math.floor(this.current*100)/100}M/${this.total}M` }}</div>
    </div>
  </div>
</template>

<script>
export default {
  data() { 
    return {
      total: 20,
      current: 0,
      timer: null
    }
  },
  methods: {
    progressing(period) {
      let _self = this;
      clearTimeout(this.timer);
      this.timer = setTimeout(function timeoutFun() {
        if (_self.current >= _self.total) {
          clearTimeout(_self.timer);
        } else {
          let random = Math.random() + 1;
          _self.current = random + _self.current > _self.total ? _self.total : random + _self.current;
          _self.updateProgress();
          let nextPeriod = Math.random() * 30 + 100;
          clearTimeout(_self.timer);
          _self.timer = setTimeout(timeoutFun, nextPeriod);
        }
      }, period);
    },
    updateProgress() {
      let percent = this.current / this.total;
      let container = document.getElementsByClassName('container')[0];
      let icon = document.getElementsByClassName('loading-icon')[0];
      let left = container.offsetWidth * percent - 20;
      if (left < 0) left = 0;
      icon.style.left = `${left}px`;
    }
  },
  computed: {
    process() {
      return this.current / this.total * 100;
    }
  },
  mounted() {
    window.onresize = this.updateProgress;
  },
  created() {
    this.progressing(100);
  }
 }
</script>

<style lang="sass" scoped>
  .progress-box
    min-width: 300px
    max-width: 900px
    padding: 0 50px
    margin: 100px auto
    .container
      position: relative
    .loading-icon
      position: absolute
      left: 0px
      top: -26px
      width: 20px
      height: 20px
      border-radius: 50%
      background-color: #000
      transition: .25s
    .loading-bar
      width: 100%
      height: 10px
      background-color: #d6e6f7
      border-radius: 20px
      .progress
        width: 0px
        height: 100%
        background-color: #007fff
        border-radius: 20px
        transition: .25s
    .loading-text
      margin-top: 6px
      text-align: right
      font-size: 14px
      color: #ccc
    
</style>

注意點:

(1)模擬數據加載的速度,涉及到了每次加載的間隔隨機,在setTimeout中的callback使用聲明函數(而不用匿名方法),用於方法內遞歸調用。

(2)寬度的百分比是參照其父元素,但是translateX(translateY)的百分比是參照其本身的寬高,因此這裏採用left屬性(以父級的寬度爲基準)來動態設置icon的位置;

(3)由於icon自身也有寬度,因此移動的距離要減去自身的寬度,這裏用js計算更爲方便,但要考慮到加載過程中若瀏覽器窗口大小改變而導致icon錯誤的問題,因此要增加監聽窗口變化的事件,重新計算icon的位置

(4)利用transition可使進度條位置的改變更爲平滑

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章