Vue 环形进度条

1,372 阅读1分钟

需求概述

第一次需求

简单的圆形进度条。

组件使用 Vue-circle-progress

Vue-circle-progress DEMO

需求变更

第二次需求

需求是需要在圆形进度条内,增加比较。

实现

使用AntV F2组件

对该DEMO进行修改

      const Shape = F2.Shape
      const G = F2.G
      const Util = F2.Util
      const Global = F2.Global
      const Vector2 = G.Vector2

      Shape.registerShape('interval', 'tick', {
        draw: function draw (cfg, container) {
          const points = this.parsePoints(cfg.points)
          const style = Util.mix({
            stroke: cfg.color
          }, Global.shape.interval, cfg.style)
          if (cfg.isInCircle) {
            let newPoints = points.slice(0)
            if (this._coord.transposed) {
              newPoints = [ points[0], points[3], points[2], points[1] ]
            }

            const _cfg$center = cfg.center
            const x = _cfg$center.x
            const y = _cfg$center.y

            const v = [ 1, 0 ]
            const v0 = [ newPoints[0].x - x, newPoints[0].y - y ]
            const v1 = [ newPoints[1].x - x, newPoints[1].y - y ]
            const v2 = [ newPoints[2].x - x, newPoints[2].y - y ]

            let startAngle = Vector2.angleTo(v, v1)
            let endAngle = Vector2.angleTo(v, v2)
            const r0 = Vector2.length(v0)
            const r = Vector2.length(v1)

            if (startAngle >= 1.5 * Math.PI) {
              startAngle = startAngle - 2 * Math.PI
            }

            if (endAngle >= 1.5 * Math.PI) {
              endAngle = endAngle - 2 * Math.PI
            }

            const lineWidth = r - r0
            const newRadius = r - lineWidth / 2

            return container.addShape('Arc', {
              className: 'interval',
              attrs: Util.mix({
                x,
                y,
                startAngle,
                endAngle,
                r: newRadius,
                lineWidth,
                lineCap: 'round'
              }, style)
            })
          }
        }
      })

      // =====重点是这里=====
      const data = [{
        x: '1',     
        y: 100,            // 红色的值,一定需要把大的值放上面
        type: '81-100' // 红色的值范围
      },
      {
        x: '1',
        y: 50,             // 蓝色的值,一定需要比红色的小
        type: '1-80'    // 蓝色的值范围
      }]
      // =====结束=====

      const chart = new F2.Chart({
        padding: 0,
        id: 'container',
        pixelRatio: window.devicePixelRatio
      })
      this.charts = chart
      chart.source(data, {
        y: {
          max: 100,
          min: 0
        }
      })
      chart.axis(false) // hide all axis
      chart.tooltip(false) // hide tooltip
      chart.legend(false) // hide tooltip
      chart.coord('polar', {
        transposed: true,
        innerRadius: 0.8,
        radius: 0.85
      }) // set polar coordinate

      chart.guide().arc({
        start: [0, 0],
        end: [1, 99.98],
        top: false,
        style: {
          lineWidth: 20,
          stroke: '#fff'
        }
      })
      chart.interval().position('x*y').size(20)
        .shape('tick')
        // ======第二个重点======
        // 随着上面 Data 设置颜色 ,顺序为:红色,渐变的蓝色,
        .color('type', ['#FA5200', 'l(180) 0:#27FFFC .5:#00B4FF 1:#27FFFC'])
        // ======结束======
        .animate({
          appear: {
            duration: 1200,
            easing: 'cubicIn',
            animation: function animation (shape, animateCfg) {
              const startAngle = shape.attr('startAngle')
              const endAngle = shape.attr('endAngle')
              shape.attr('endAngle', startAngle)
              shape.animate().to(Util.mix({
                attrs: {
                  endAngle
                }
              }, animateCfg)).onUpdate(function (frame) {
              })
            }
          }
        })
      chart.render()