web canvas -- 实现环形进度条

1,810 阅读2分钟

canvas 实现环形进度条

效果

代码

    var canvas = document.getElementById('myCanvas');
    var ctx = canvas.getContext("2d");

	
	/**
        * @author xie xiu yue
        * @licence MIT
        * @description https://juejin.cn/post/6844904056658329613
        */
	/**
         * 绘制圆形进度条
         * @param {number} angle 
         * @param {number} x 
         * @param {number} y 
         * @param {number} radius 
         * @param {Object} option 
         */
        var drawRoundProgress = (ctx, angle, x, y, radius, option) => {
            /**
             * 绘制单个圆形进度
             * @param {Object} o 
             */
            var drawCircle = (o) => {
              var ctx = o.ctx
              ctx.beginPath();
              ctx.lineWidth = o.lineWidth
              ctx.arc(o.x, o.y, o.radius, 1.5 * Math.PI, (1.5 + (o.angle * 2)) * Math.PI,false);
              ctx.lineCap = 'round';
              ctx.strokeStyle = o.color
              ctx.stroke();
              ctx.closePath();
            }
              drawCircle({
                  ctx,
                  angle: 1,
                  color: option.layerColor,
                  lineWidth: 3,
                  x: x + radius,
                  y: y + radius,
                  radius,
              })
              drawCircle({
                  ctx,
                  angle,
                  color: option.fill,
                  lineWidth: 6,
                  x: x + radius,
                  y: y + radius,
                  radius,
              })
        }
        

        // 应用
        drawRoundProgress(ctx, 10 / 100, roundY + rem(101), roundX + rem(608), rem(162) / 2, {
            layerColor: '#1F67A5',
            fill: '#FFDF00',
        })

代码解析

核心就是ctx.arc函数

ctx.arc(o.x, o.y, o.radius, 1.5 * Math.PI, (1.5 + (o.angle * 2)) * Math.PI,false);

前两个是中心坐标 也就是 x和y
第三个是半径
第三个和第四个是开始和结束的角度
最后是是否顺时针

牛刀小试

了解了核心,那么我们来试试实现上面的效果。

var drawCircle = (o) => {
		ctx.beginPath();
		ctx.lineWidth = o.lineWidth
		ctx.arc(o.x, o.y, o.radius, 0, Math.PI * 0.5,false);
		ctx.strokeStyle = o.color
		ctx.stroke();
		ctx.closePath();
	}
	drawCircle({
		angle: 0.1,
		color: '#FFDF00',
		lineWidth: 6,
		x: 50,
		y: 50,
		radius: 30,
	})

运行结果

???

怎么不太对,圆角哪里去了,起点怎么变成右方。

圆角

既然核心函数没有圆角,那么就是别的地方设置。

找女朋友一样找就可以找到

ctx.lineCap = 'round';

这行代码,加上去后就有了圆角。

但是起点不太对啊。效果图是从顶部开始。

角度问题

这时候我们需要看下面这张宝图

开始的角度

可以看到。0是在右方,而1.5才是开始,于是我们先设置开始为 1.5 * Math.PI

有了开始,我们需要结束

结束的角度设置

因为开始是1.5。于是需要设置偏移量1.5,但是这时候我们发现一圈是2,这样不好计算,于是需要转成1,等下方便传入百分比,于是这样写 (1.5 + (angle * 2)) * Math.PI

现在angle是多少,我们就会正确显示

所以代码

再次牛刀小试

ctx.arc(o.x, o.y, o.radius, 1.5 * Math.PI, (1.5 + (o.angle * 2)) * Math.PI,false);

好,完美。

--完--