封装了一个UILabel并让它显示圆形的边框,UILabel上面显示百份比,而边框则用Animation绘制到整个圆占指定百分比的点。

                                                               

这只是我个人想的继承一个UILabel实现的,用到两个CAShapeLayer,第一个Layer的作用是画出灰色的背影圆圈,第二个Layer位置放置在第一个Layer的上面,并设置为红色描绘颜色并描绘到插定的位置,之后实现相应的动画效果即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import UIKit
 
class kCircleLabel: UILabel {
     
    var percent:Double!
     
    convenience init(percent per:Double,frame:CGRect) {
        self.init(frame: frame)
        self.percent = per
        createCircle()
    }
     
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
     
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
     
    func createCircle() {
        self.textAlignment = NSTextAlignment.Center
        self.text = "\(percent * 100 )%"
         
         
        //第一个圆形Layer,边框为灰色的
        let circleLayer:CAShapeLayer = CAShapeLayer()
        circleLayer.lineWidth = 8
        //清除填充的颜色
        circleLayer.fillColor = UIColor.clearColor().CGColor
        //边框的颜色
        circleLayer.strokeColor = UIColor.init(red: CGFloat(220.0 / 255.0 ), green: CGFloat(220.0 / 255.0), blue: CGFloat(220.0 / 255.0), alpha: 1.0).CGColor
         
        //用贝塞尔曲线画出一个圆
        let circlePath:UIBezierPath = UIBezierPath(ovalInRect: CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height))
         
        circleLayer.path = circlePath.CGPath
        self.layer.addSublayer(circleLayer)
         
         
         
         
        //第二个只描绘到特定位置的弧Layer
        let arcLayer:CAShapeLayer = CAShapeLayer()
         
        //画出特定的弧
        let arcPath:UIBezierPath = UIBezierPath(arcCenter: CGPoint(x: self.frame.size.width / 2, y: self.frame.size.height / 2), radius: self.frame.size.width / 2, startAngle: 0.0, endAngle: CGFloat(360 * percent / 180 * M_PI), clockwise: true)
         
        arcLayer.path = arcPath.CGPath
        arcLayer.lineWidth = 8
        //清除填充的颜色
        arcLayer.fillColor = UIColor.clearColor().CGColor
        arcLayer.strokeColor = UIColor.redColor().CGColor
         
        //弧Layer的动画
        let arcAnimation:CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd")
        arcAnimation.fromValue = 0.0
        arcAnimation.toValue = 1.0
        arcAnimation.duration = 1.5
        arcAnimation.removedOnCompletion = false
        arcAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
         
        //这是从大到小的动画,适用于整个Layer
        let scaleAnimation:CABasicAnimation = CABasicAnimation(keyPath: "transform.scale")
        scaleAnimation.fromValue = 5.0
        scaleAnimation.toValue = 1.0
        scaleAnimation.duration = 0.5
         
        arcLayer.addAnimation(arcAnimation, forKey: nil)
         
        /*let animationGroup:CAAnimationGroup = CAAnimationGroup()
        animationGroup.duration = 1.0
        animationGroup.animations = [ arcAnimation, scaleAnimation]*/
         
        self.layer.insertSublayer(arcLayer, above : circleLayer)
        self.layer.addAnimation(scaleAnimation, forKey: nil)
 
    }
     
     
     
     
     
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    //override func drawRect(rect: CGRect) {
        // Drawing code
    //}
     
 
}

 调用时:

 let circleLabel = kCircleLabel(percent: 0.52, frame: CGRect(x:  (self.view.bounds.width - 100.0) / 2, y: 260, width: 100.0, height: 100.0))

 self.view.addSubview(circleLabel)

 要实现这个效果的关键是要学会怎么使用贝塞尔曲线,并给Layer设置Path。