基于canvas 2D实现微信小程序自定义组件-环形进度条
最近开发一个小程序项目博闻金榜答题小程序,需要使用到一个可以显示答题倒计时的组件,基于进度条实现,下面就主要介绍基于canvas2D实现一个环形进度条微信小程序自定义组件,文中有示例代码,写的比较粗陋,感兴趣的小伙伴们可以讨论交流
本文实例为大家分享了微信小程序实现环形进度条的具体代码,具体实现功能如下
- 参考微信小程序自定义组件官方教程
- 实现进度渐变
- 实现颜色渐变
先上效果图(录制不清晰,凑合着看v)
开发步骤
1、在根目录创建名为components的文件夹,用来放需要引用的自定义组件。
2、创建名为circle的文件夹,用来放环形进度条自定义组件。
3、代码拷贝到对应目录下即可正常使用
目录结构图:
主要代码,代码比较简单,文中有相应的注释(完整项目,最后有下载地址)
circle.json
{
"component": true,
"usingComponents": {}
}
circle.wxml
<canvas id="myCanvas_circle" >
<view class="circle-bar" style="height:{{canvasWidth}}px;">
<view class="title_name">
{{title}}
</view>
<view class="title_val" >
{{value}} {{suffix}}
</view>
</view>
</canvas>
circle.wxss
.circle-bar{
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
position: absolute;
top: 0;
}
.circle-bar .title_name{
max-height: 62rpx;
font-size: 26rpx;
overflow:hidden;
text-overflow:ellipsis;
display:-webkit-box;
-webkit-box-orient:vertical;
-webkit-line-clamp:2;
}
circle.js
_setPercent: function (per, old) {
var ctx = this.data.ctx2d;
if (!ctx) {
return;
}
// 大小值的计算
var circle_r = this.data.canvasWidth / 2; //画布的一半,用来找中心点和半径
var startDegree = this.data.startDegree; //从什么角度开始
var maxValue = this.data.maxValue; //最大值
var minValue = this.data.minValue; //最小值
var lineColor = this.data.lineColor; //线条颜色
var lineWidth = this.data.lineWidth; //线条宽度
var percent = 360 * ((this.data.value - minValue) / (maxValue - minValue)); //计算结果
var direction = false; //默认顺时针
//根据差值计算
if (per > old) {
//绘制彩色
if (this.data.isColours) {
//设置渐变色
var my_gradient = ctx.createLinearGradient(0, 0, 200, 0);
my_gradient.addColorStop(0, this.data.lineColor);
my_gradient.addColorStop(0.5, "red");
my_gradient.addColorStop(1, "#FA6400");
lineColor = my_gradient;
}
startDegree = 360 * ((old - minValue) / (maxValue - minValue));
percent = 360 * (((per - old) - minValue) / (maxValue - minValue))
} else {
//绘制灰色,反向绘制
lineColor = "#ebebeb";
direction = true;
startDegree = 360 * ((old - minValue) / (maxValue - minValue));
percent = 360 * (((old - per) - minValue) / (maxValue - minValue))
}
//绘制有色彩的圆弧
var currtnt_st = 0; //绘制进度
var step = 10;
var span = 200 * step / (percent); //200ms完成绘制
var drawInterval = setInterval(() => {
currtnt_st = currtnt_st + step;
if (currtnt_st > percent) {
currtnt_st = percent;
}
ctx.beginPath();
ctx.strokeStyle = lineColor;
ctx.lineWidth = lineWidth;
if (!direction) {
ctx.arc(0, 0, circle_r - 10, startDegree * Math.PI / 180 - 0.5 * Math.PI, (startDegree + currtnt_st) * Math.PI / 180 - 0.5 * Math.PI, direction);
} else {
ctx.arc(0, 0, circle_r - 10, startDegree * Math.PI / 180 - 0.5 * Math.PI, ((startDegree - currtnt_st) * Math.PI / 180) - 0.5 * Math.PI, direction);
}
ctx.stroke();
ctx.closePath();
if (currtnt_st >= percent) {
clearInterval(drawInterval);
}
}, span);
}
使用组件
index.json
{
"navigationBarTitleText": "测试页面",
"usingComponents": {
"circle": "/components/circle/circle"
}
}
index.wxml
<view class="circle-ps">
<circle type="2d" id="can" canvasWidth="{{80}}" value="{{per}}" valueColor="#333" lineWidth="{{3}}"></circle>
</view>
<view class="circle-ps">
<circle type="2d" name="cans1" canvasWidth="{{90}}" value="{{per1}}" valueColor="#333" lineWidth="{{3}}"></circle>
</view>
index.js
setInterval(() => {
this.setData({
per:parseInt(Math.random()*100),
per1:parseInt(Math.random()*100),
})
}, 1000);
组件的属性介绍
属性名称 | 类型 | 默认值 | 说明 |
---|---|---|---|
画布宽度 | float | 100%*0.4 | 画布默认大小 |
线条宽度 | float | 10 | 环形线条粗细 |
线条颜色 | string | “#3696FA” | 颜色代码 |
标题 | string | “完成率” | |
最大值 | int | 100 | |
最小值 | int | 0 | |
值后缀 | string | % | |
开始角度 | int | 0 | 开始绘制圆环的角度(0-360) |
是否开启渐变 | bool | false | 是否启用圆环进度颜色渐变 |
环形进度条的组件完整代码:
下载完整源码