美文网首页Vue.jsVue.js专区
vue实现canvas自适应3/4圆环进度条

vue实现canvas自适应3/4圆环进度条

作者: 泛酸的桂花酒 | 来源:发表于2019-10-11 09:41 被阅读0次

    演示地址
    完整代码地址

    效果如图

    image.png

    方案背景

    需求

    1.圆环需要呈现3/4进度条
    2.小球跟随数字大小而准确落在正确的位置
    3.可以配置舒适范围的颜色
    4.当超出舒适范围变为红色,超出剩余部分变为红色

    对应方案

    1.用canvas实现3/4圆环
    2.利用坐标系计算出小球的位置
    3.利用容器百分比实现自适应
    4.对应颜色范围使用弧长公式计算

    代码实现

    在canvas上面定义一个父容器,canvas使用百分比inline-block来达到自适应,
    父容器可以使用vw,em等自适应单位就可以达到自适应效果,我这里已经做了全局转换为vw

    <template>
      <div class="canvas">
        <canvas :id="id"
                style="width:100%;height:100%;display: inline-block;"></canvas>
      </div>
    </template>
    <style lang="scss" scoped>
      .canvas {
        display: block;
        margin: 0 auto;
        /*margin-top: 10px;*/
        width: 150px;
        height: 75px;
      }
    </style>
    

    定义data和props来接受父组件配置的数据和定义弧长半径数值等

      data() {
        return {
          // num: 0,
          canvas: '',
          context: '',
          cirX: '',
          cirY: '',
          rad: '',
          n: 1,
          speed: 150,
          r: 24
        }
      },
      //percents 范围开始值  percente 范围结束值 num数值  WarningColor错误颜色  ballColor小球颜色 ratioColor 外圈范围值颜色  OuterColor
      props: ['percents', 'ratioColor', 'id','percente','num','WarningColor',"ballColor","OuterColor"],
      mounted() {
        this.canvas = document.getElementById(this.id)
        this.context = this.canvas.getContext('2d')
        this.context.scale(2, 2);
        (this.cirX = 30), //this.canvas.width/ 2
          (this.cirY = 30), //this.canvas.height/ 2
          (this.rad = (Math.PI * 2*0.75) / 100)
        this.DreamLoading()
      },
    

    绘制圆弧方法入口
    其实这是一个不断重复绘制,requestAnimationFrame用作于动画浏览器会自动作用最佳的动画时间间隔。每次移动0.4来达到小球运动的效果

        DreamLoading() {
          // console.log(this.n)
          //清除所有,重新绘制
          this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
          this.writeCircle()
          this.writeText(this.n)
          if(this.num < this.percents || this.num > this.percente) {
            this.writeWarningColor()
          }
          if(this.num >= this.percents && this.num <= this.percente)  {
            this.writeBlueS()
          }
          this.writeSmallCircle(this.n)
          //      if(this.n < 100 && this.n <= 60){
          var count = this.num
          if (this.n <= count) {
            this.n = this.n + 0.4
          } else {
            return (this.n = 0)
          }
          requestAnimationFrame(this.DreamLoading)
        }
    

    绘制外围的3/4圈,从1/4Π开始到7/4Π就是一个3/4圆(一个圆是2Π也就是8/4Π)

        writeCircle() {
          this.context.save() //save和restore可以保证样式属性只运用于该段canvas元素
          this.context.beginPath() //开始路径
          this.context.strokeStyle = this.OuterColor //设置边线的颜色
          this.context.lineWidth = 4
          this.context.arc(
            this.cirX,
            this.cirY,
            this.r,
            Math.PI * 0.75,
            Math.PI * 2.25,
            false
          ) //画一个3/4圆的路径
          this.context.stroke() //绘制边线
          //      this.context.restore();
          //         this.context.closePath();
        },
    

    绘制舒适范围值要加上弧长即可

       writeBlueS() {
          this.context.save()
          this.context.strokeStyle = this.ratioColor
          this.context.lineWidth = 4
          this.context.beginPath()
          this.context.arc(
                  this.cirX,
                  this.cirY,
                  this.r,
                  Math.PI * 0.75 + this.percents*this.rad,
                  Math.PI * 0.75+ this.percente*this.rad,
                  false
          ) // 4/3处开始画
          this.context.stroke()
          this.context.restore()
        },
    

    绘制警告范围值也是同样

        writeWarningColor() {
          this.context.save()
          this.context.strokeStyle = this.WarningColor
          this.context.lineWidth = 4
          this.context.beginPath()
          this.context.arc(
            this.cirX,
            this.cirY,
            this.r,
            Math.PI * 0.75 + this.percente*this.rad,
            Math.PI * 2.25,
            false
          ) // 4/3处开始画
          this.context.stroke()
          this.context.restore()
        },
    

    绘制文本,付按揭是计算好圆心的位置

        writeText(n) {
          this.context.save()
          this.context.font = '30px Arial'
          this.context.fillStyle = 'rgba(255,255,255,1)' //字体颜色
          this.context.fillText(n.toFixed(0), this.cirX-18, this.cirY + 10) //绘制实心
          //context.strokeStyle = "#49f";
          // context.strokeText(n.toFixed(0)+"%",cirX - 30 ,cirY +10); //绘制空心
          this.context.stroke()
          this.context.restore()
        },
    

    绘制小球和小球运动轨迹 关键在于这个xpos ypos的坐标公式

        writeSmallCircle(n) {
          this.context.save()
          this.context.fillStyle = this.ballColor;
          // this.context.lineWidth = 12;
          let angle =2.25 * Math.PI  - this.rad * n;
          let xPos =- Math.cos(angle) * (this.r) + 58/2;
          let yPos = Math.sin(angle) * (this.r) + 58/2;
          this.context.beginPath()
          this.context.arc(xPos,yPos, 5, 0,Math.PI * 2, true) // 4/3处开始画
          this.context.fill()
          this.context.restore()
          //画小球的边框
          this.context.save()
          this.context.lineWidth = 1
          this.context.strokeStyle ='rgba(255,255,255,1)';
          this.context.beginPath()
          this.context.arc(xPos,yPos, 5, 0,Math.PI * 2, true) // 4/3处开始画
          this.context.stroke()
          this.context.restore()
    
        },
    
    组件用法

    引入组件

    import canvasCircle from "./circle.vue";
      components: {
        canvasCircle,
      },
    

    data里面定义

      cicleList: [
            {
              Number:'26',
              startRadio: "12", //舒适范围值
              endRadio: "46",
              ballColor:"rgba(208, 232, 254, 1)",
              OuterColor:'rgba(208, 232, 254, 1)',
              ratioColor: "rgba(68, 163, 252, 1)" //外圈颜色
            }
          ],
    

    页面使用

                  <canvas-circle
                        v-for="(item, index) in cicleList"
                        :key="index"
                        :ballColor="item.ballColor"
                        :num="item.Number"
                        :percents="item.startRadio"
                        :percente="item.endRadio"
                        :OuterColor="item.OuterColor"
                        :ratioColor="item.ratioColor"
                        :id="index + 'circle'"
                      ></canvas-circle>
    

    相关文章

      网友评论

        本文标题:vue实现canvas自适应3/4圆环进度条

        本文链接:https://www.haomeiwen.com/subject/pkjapctx.html