微信小程序自定义环形进度条组件开发

531 阅读3分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。

image.png

前言

前几天设计又更改了设计图,要求把统计模块换成环形统计图并要求环形填充度数据为当前圆形的百分之xx,一开始看了echarts,也是可以实现而且也很简单,但是发现灵活性不是很大,改动也比较麻烦些,决定用canvas画一个。

canvas画圆

1.创建组件,我是单独放在components里

image.png

2.创建最外侧圆形的轮廓

这里用的是2.5rpx,估算2.5rpx等于1px(自行测算) borderColor轮廓颜色 (为了该组件重复调用而设定)

<view class="round" style="border: 2.5rpx solid {{borderColor}};"></view>

用flex的目的是为了将文字和元素内的所有元素居中,这样就展示出了外边的大轮廓

.round{
  width:100%;
  height:100%;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

3. 继续画内轮廓

内轮廓为了适用各个场景下的使用场合,所以把宽度和高度都做了自定义设置,方便使用

<canvas style="width:{{canvasWidth}}px;height:{{canvasWidth}}px;" canvas-id="circleBar"></canvas>

不要忘了在加载的时候创建canvas

var ctx = wx.createCanvasContext("circleBar", this);

4. 内轮廓填充色

内轮廓填充色,说白了是新创建了一模一样的内轮廓,只不过颜色不一样而已(方便自定义)

<view class="circle-bar-wrap" style="height:{{canvasWidth}}px;"></view>

flex-direction: column竖向排列居中

.circle-bar-wrap {
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  box-sizing: border-box;
}

5.数据展示

背景色为渐变色background: linear-gradient(#FFFFFF, #C1C1C1); 在这一步也为.val设置了align-items: center;justify-content: center;防止数据不居中而设置

<view class="val" style="color: {{valueColor}}; margin-top:{{isMarginTop?'0':'0'}}rpx;background: linear-gradient(#FFFFFF, #C1C1C1);">
    {{value}}
</view>
  width: 68%;
  height: 68%;
  font-size: 50rpx;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;

6.创建画布

开发的是组件,所以要在Component({})里添加methods方法;

Component({
    mehtods:{}
})

methods方法里设置公共方法,方便调用组件的时候进行初始化

showCanvas() {
    var ctx = wx.createCanvasContext("circleBar", this); 
}

设置圆形中心点和起始点

最重要的核心点是找到当前圆形的中心点,不然一切数据都是错乱的,画布的宽度默认占屏幕宽度的0.4倍 ctx.translate为canvas方法

var circle_r = wx.getSystemInfoSync().windowWidth *0.4 / 2;
ctx.translate(circle_r, circle_r);

百分比设置

properties:{
    //最大值 默认100
    maxValue: {
      type: Number,
      value: 100
    },
    //最小值 默认0
    minValue: {
      type: Number,
      value: 0
    },
}
  var maxValue = this.data.maxValue; //最大值
  var minValue = this.data.minValue; //最小值

圆形开始的角度

一般初始化的时候如果数据不为0,那么填充色开始从那个角度开始填充,角度为0-360度之间**(12点方向为0,18点方向为180,0点方向为360)** 计算公式:360 * ((当前值-最小值)/ (最大值-最小值))

properties:{
    startDegree: {
      type: Number,
      value: 0
    },
}
var startDegree = this.data.startDegree //90;
var percent = 360 * ((value - minValue) / (maxValue - minValue)); //计算结果

填充canvas线条颜色和线条宽度

lineColor和lineWidth都是引入组件传入的值

var lineColor = this.data.lineColor; //线条颜色
var lineWidth = this.data.lineWidth; //线条宽度
//填充颜色和宽度
ctx.setStrokeStyle(lineColor);
ctx.setLineWidth(lineWidth);

画线和路径

两个圆弧,一个为灰色圆弧,一个为彩色圆弧,这里是分别设置的 记得要加上ctx.closePath();

//灰色
ctx.arc(0, 0, circle_r - 10, 0, 2 * Math.PI, true);
ctx.stroke();
ctx.closePath();
//彩色
ctx.arc(0, 0, circle_r - 10, startDegree * Math.PI / 180 - 0.5 * Math.PI, percent * Math.PI / 180 + startDegree * Math.PI / 180 - 0.5 * Math.PI, false);
ctx.stroke();
ctx.closePath();

调用

usingComponents引入组件

"canvas-round": "/components/canvas-round/canvas-round"

wxml引入

这里分别传入了borderColor颜色canvasWidth宽度value

<canvas-round id="canvasRingA" borderColor="#5AC8FA54" canvasWidth="{{67}}"value="{{10}}" lineColor="#5AC8FA"></canvas-round>

onReady的时候对该组件进行初始化

使用selectComponent构造器初始化,然后进行调用

var canvasRoundA = this.selectComponent("#canvasRingA");
canvasRoundA.showCanvasRing();