微信小程序圆环形进度条组件
首先理解小程序的自定义组件。
原理
看了网上的一些教程,实现圆环用的是两个半圆的旋转,通过overflow: hidden
来控制的。
首先绘制底层容器,一个正方形,通过圆角变圆,用来作为未读进度的圆环。然后在上面绘制两个半矩形,在圆形矩形中绘制两个半圆(通过border-left/right/top/bottom
加上旋转角来实现,默认的旋转角为135°)。
overflow: hidden
,就会有如下的效果。
WXML
代码:
由于必须通过js来控制style,所以不能写进wxss
文件里,实在是很丑。
<view class='circle-progress-container' style="width: {{size}}rpx;height: {{size}}rpx;">
<view class="circle-progress-outter-circle" style="width: {{size}}rpx;height: {{size}}rpx;border: {{borderSize}}rpx solid {{normalColor}};">
</view>
<view class='circle-progress-half-rect right-rect' style="width: {{size/2+1}}rpx;height: {{size}}rpx;">
<view wx:if="{{currentProgress>0}}" class='circle-progress-half-circle right-circle' style="transform: rotate({{rightCircleRadius}}deg);width: {{size}}rpx;height: {{size}}rpx; border: {{borderSize}}rpx solid transparent;border-right: {{borderSize}}rpx solid {{borderColor}};border-bottom: {{borderSize}}rpx solid {{borderColor}};" ></view>
</view>
<view class='circle-progress-half-rect left-rect' style="width: {{size/2+1}}rpx;height: {{size}}rpx;">
<view wx:if="{{currentProgress>0.5}}" class='circle-progress-half-circle left-circle' style="transform: rotate({{leftCircleRadius}}deg);width: {{size}}rpx;height: {{size}}rpx; border: {{borderSize}}rpx solid transparent;border-left: {{borderSize}}rpx solid {{borderColor}};border-top: {{borderSize}}rpx solid {{borderColor}};"></view>
</view>
</view>
CSS
代码如下:
.circle-progress-outter-circle{
border-radius: 50%;
box-sizing: border-box;
}
.circle-progress-half-rect{
position: absolute;
overflow: hidden;
}
.right-rect{
top: 0;
right: 0;
}
.left-rect{
top: 0;
left: 0;
}
.circle-progress-half-circle{
border-radius: 50%;
box-sizing: border-box;
position: absolute;
}
.right-circle{
top:0;
right: 0;
transform: rotate(-45deg);
}
.left-circle{
top:0;
left: 0;
transform: rotate(-45deg);
}
组件的JS:
Component({
properties: {
currentProgress:{
type: Number,
value: 0,
observer: '_progressDidChange',
},
size:{
type: Number,
value: 200
},
borderSize:{
type: Number,
value: 20
},
borderColor:{
type: String,
value: "green"
},
normalColor:{
type: String,
value: "gray"
}
},
data: {
rightCircleRadius: 135,
leftCircleRadius: 135,
},
methods: {
_progressDidChange: function(newVal,oldVal){
var that = this;
var newLeftRadius = that.data.leftCircleRadius;
var newRightRadius = that.data.rightCircleRadius;
var radius = 360 * newVal;
if(newVal < 0.5 && newVal >= 0){
//只需要旋转右边的值
newLeftRadius = 135;
newRightRadius = 135 + radius;
}else if(newVal <= 1 && newVal >=0.5){
//两边都需要旋转
newLeftRadius = radius - 45;
newRightRadius = -45;
}
that.setData({rightCircleRadius:newRightRadius,leftCircleRadius:newLeftRadius});
}
}
})
顺时针还是逆时针的话,只需要调整_progressDidChange
里的函数就可以了。
使用组件
<circle-progress wx:if="{{isPlaying}}" size="54" normalColor="#eaeaea" borderColor="#BF831E" borderSize="4" currentProgress="{{progress}}"></circle-progress>
- borderSize: 表示进度条粗细。
- borderColor: 表示进度条颜色。
- normalColor: 表示未读进度条颜色。
- progress: 在外部通过
page.setData()
函数来设置实时进度。 - size:圆环的尺寸。
别忘了在page.json
里声明
"usingComponents": {
"circle-progress": "/components/circle-progress/circle-progress"
}