微信小程序圆环形进度条组件


首先理解小程序的自定义组件

原理

看了网上的一些教程,实现圆环用的是两个半圆的旋转,通过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"
  }

xferris

我都不了解我自己

西安·深圳

Subscribe to 慎独

欢迎使用邮件订阅本博客

or subscribe via RSS with Feedly!