封装了一个UILabel并让它显示圆形的边框,UILabel上面显示百份比,而边框则用Animation绘制到整个圆占指定百分比的点。
这只是我个人想的继承一个UILabel实现的,用到两个CAShapeLayer,第一个Layer的作用是画出灰色的背影圆圈,第二个Layer位置放置在第一个Layer的上面,并设置为红色描绘颜色并描绘到插定的位置,之后实现相应的动画效果即可。
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, 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, 100.0, height: 100.0))
self.view.addSubview(circleLabel)
要实现这个效果的关键是要学会怎么使用贝塞尔曲线,并给Layer设置Path。