一个简单的圆环倒计时组件

1,416 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1.我们先来写css html模板

写下来大概就是用svg path先画一个圆环轨道,在用另一层带颜色的 path去覆盖颜色。圆环中的倒计时先用一个变量占位,这里还初始化了一个ps的css样式变量'stroke-dasharray': '0, 0'记住后面让圆环进度条动起来全靠它了

2.让我们再来写一个倒计时先让倒计时先动起来

//这里在state里初始化了 countDownSeconds 属性 用来记录倒计时的总秒数
//在Mounted阶段调用 timingstart方法开始计时 
//使用computed计算方法 每次倒计时动态更新换算成对应时间
  const state = reactive({
      ps: {
        'stroke-width': '40px',
        'stroke-dasharray': '0, 0',
      },
      countdowntext:'倒计时',
      countDownSeconds: 900, //900秒相当于 15分钟
      t:null
    })
    onMounted(() => {
      timingstart()
    })

    const countdownValue = computed(() => {
      return countdownTime(state.countDownSeconds)
    })

    const countdownTime = (Seconds = 60) => {
        var d = parseInt(Seconds / 60 / 60 / 24); //获取天数
        var h = parseInt(Seconds / 60 / 60 % 24); //获取小时数
        var m = parseInt(Seconds / 60 % 60); //获取分钟数
        var s = parseInt(Seconds % 60); //获取秒数
        m = m < 10 ? '0' + m : m;
        s = s < 10 ? '0' + s : s;
        return `${m}:${s}`
    }

    function timingstart() {
      state.countDownSeconds--;
      if (state.countDownSeconds <= 0) {
        console.log('倒计时结束')
        clearTimeout(state.t)
      } else {
        state.t = setTimeout(() => {
          timingstart()
        }, 1000)
      }
    }

    return {
      ...toRefs(state),
      countdownValue
    }
    

3.圆环内的倒计时已经动起来了,接下来我们需要做些修改来让时间和圆环的进度条保持同步

这里开始没想到可以用 stroke-dasharray 属性来控制进度条的加载 之前看过vant 的圆环组件是使用stroke-dasharray这个属性来控制进度条的加载(心血来潮想照着模仿一个)代码趴下来 发现 stroke-dasharray: 2198px, 3140px; 这个有意思的css属性,经过调试大概猜出来两个属性值的意思2198px代表了当前的圆环进度,而3140px代表着总进度

想到这里感觉那这就好办了呀 但是仔细一想我当前的进度可以计算得来也就是stroke-dasharray的第一个属性值但是,我第二个总进度条的长度(我不能写死呀,这样就不灵活了)是从何而来呢?然后好巧不巧当天晚上在B站上刷到了一条关于svg动画的教学,好家伙正好发现了可以获取svgpath路径总长度的方法 getTotalLength (真是天助我也哈哈哈哈哈,下面代码有注释。)可以开心写js代码了。

    const state = reactive({
      ps: {
        'stroke-width': '41px',
        'stroke-dasharray': '0, 0',
      },
      countDownSeconds: 900, //900秒相当于 15分钟
      activeprogress: 0, //当前进度
      stepSeconds:0,
      t: null,
    })
    
    onMounted(() => {
      let cir = document.getElementById('cir')
      let circleTotalLength = parseInt(cir.getTotalLength()) //获取path路径总长度的方法
      //每秒走的进度
      state.stepSeconds = Number((circleTotalLength/state.countDownSeconds).toFixed(2)) 
      timingstart(state.stepSeconds,circleTotalLength)
    })


    function timingstart(step_,circleTotalLength) {
      state.countDownSeconds--;
      state.activeprogress += step_ 
      state.ps = {
        'stroke-width': '41px',
        'stroke-dasharray': `${state.activeprogress.toFixed(2)}px,${circleTotalLength}px`,
      }
      if (state.countDownSeconds <= 0) {
        console.log('倒计时结束')
        clearTimeout(state.t)
      } else {
        state.t = setTimeout(() => {
          timingstart(state.stepSeconds,circleTotalLength)
        }, 1000)
      }
    }
    

好了到这里代码也写完了代码,其他地方还有优化的空间,这次只是写个例子提供大家参考。

如果这篇文章有帮助到你,❤️点赞❤️鼓励一下作者,谢谢大家