js绘制圆环进度条

简介:

        主要是利用HTML中的requestAnimationFrame利用浏览器的刷新去推进进度条,进度条主要是生成2D的canvas来显示

最终效果:

 主要代码:

<template>
  <div class="container">
    <canvas id="canvas" width="600" height="900">
      <p>加载失败</p>
    </canvas>
  </div>
</template>
<script>
import { onMounted, reactive, toRefs } from 'vue'
export default {
  setup(){
    const state = reactive({
      canvas:null,
      ctx:null,
      circleX:null,
      circleY:null,
      radius:100,
      percent:100,
      lineWidth:1,
      fontSize:42,
      startnum:0,
      timer:null, // 加载帧
    })
    /**
      * @description 画圆
    */
    function circle(cx,cy,r){
      state.ctx.beginPath()
      state.ctx.lineWidth = state.lineWidth
      state.ctx.strokeStyle = '#666666'
      state.ctx.lineCap = 'round'
      state.ctx.shadowColor = '#000000'
      state.ctx.shadowBlur = 0
      state.ctx.shadowOffsetX = 0
      state.ctx.shadowOffsetY = 0
      state.ctx.arc(cx,cy,r + 10,0,(Math.PI / 180) * 360)
      state.ctx.moveTo(cx + r,cy)
      state.ctx.arc(cx,cy,r,0,(Math.PI / 180) * 360)
      state.ctx.stroke()
    }
    /**
     * @description 画弧线
    */
    function sector(cx,cy,r,startAngle,endAngle,anti) {
      state.ctx.beginPath()
      state.ctx.moveTo(cx,cy - r - 5) // 从圆形底部开始绘画
      state.ctx.lineWidth = 12
      state.ctx.strokeStyle = '#ffccff'
      /**
       * @description 圆弧两端样式
      */
      state.ctx.lineCap = 'round'
      state.ctx.shadowColor = '#f600f6'
      state.ctx.shadowOffsetX = 0
      state.ctx.shadowOffsetY = 0
      state.ctx.shadowBlur = 4
      /**
       * @description 画弧
      */
      state.ctx.arc(
        cx,
        cy,
        r + 5,
        startAngle * (Math.PI / 180.0) - Math.PI / 2,
        endAngle * (Math.PI / 180.0) -Math.PI / 2,
        anti
      )
      state.ctx.moveTo(cx,cy - r)
      state.ctx.moveTo(cx,cy - r)
      state.ctx.stroke()
    }
    /**
     * @description 画遮盖
    */
    function cover(cx,cy,r) {
      state.ctx.beginPath()
      state.ctx.moveTo(cx,cy - r)
      state.ctx.clearRect(cx - 8,cy - r -18,6,30)
    }
    /**
     * @description 画黑色小号圆遮盖中间部分
    */
    function sectorCover(cx,cy,r,startAngle,endAngle,anti) {
      state.ctx.beginPath()
      state.ctx.moveTo(cx,cy - r - 5) // 从圆形底部开始绘画
      state.ctx.lineWidth = 10
      state.ctx.strokeStyle = '#000000'
      /**
       * @description 圆弧两端样式
      */
      state.ctx.lineCap = 'round'
      state.ctx.shadowColor = '#000000'
      state.ctx.shadowOffsetX = 0
      state.ctx.shadowOffsetY = 0
      state.ctx.shadowBlur = 0
      /**
       * @description 画弧
      */
      state.ctx.arc(
        cx,
        cy,
        r + 5,
        startAngle * (Math.PI / 180.0) - Math.PI / 2,
        endAngle * (Math.PI / 180.0) -Math.PI / 2,
        anti
      )
      state.ctx.moveTo(cx,cy - r)
      state.ctx.moveTo(cx,cy - r)
      state.ctx.stroke()
    }
    /**
     * @description 刷新
    */
    function loading(n) {
      state.ctx.clearRect(0,0,state.circleX * 2,state.circleY * 2) // 清除canvas内容
      /**
       * @description 中间的字
      */
     console.log('size',state.fontSize);
      state.ctx.shadowColor = '#f600f6'
      state.ctx.shadowBlur = 4
      state.ctx.font = state.fontSize + 'px April'
      state.ctx.textAlign = 'center'
      state.ctx.textBaseline = 'middle'
      state.ctx.fillStyle = '#ffccff'
      state.ctx.fillText(parseInt(n).toFixed(0) + '%',state.circleX,state.circleY)
      /**
       * @description 圆形
      */
      circle(state.circleX,state.circleY,state.radius)
      /**
       * @description 圆弧
      */
      sector(state.circleX,state.circleY,state.radius,0,(n / 100) * 360)
      sectorCover(state.circleX, state.circleY, state.radius, 0, (n / 100) * 360) // 黑色小号实心圆充当背景遮挡
      cover(state.circleX,state.circleY,state.radius)
    }
    /**
     * @description 循环
    */
    async function loop() {
      state.startnum = state.startnum + 1
      await loading(state.startnum)
      state.timer = requestAnimationFrame(loop)
      if(state.startnum === 100){
        cancelAnimationFrame(state.timer)
      }
    }
    onMounted(() =>{
      state.canvas = document.getElementById('canvas')
      state.ctx = state.canvas.getContext('2d')
      state.circleX = state.canvas.width / 2
      state.circleY = state.canvas.height / 2
      loop()
    })
    return {
      ...toRefs(state)
    }
  }
}
</script>
<style>
.container{
  background-color: #000000;
}
</style>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值