一种方法是用
CAGradientLayer
掩盖 CAShapeLayer
。形状图层应有一个圆弧作为其 path
,并且 lineCap
为 .round
。
class FadingProgressView: UIView {
let shapeLayer = CAShapeLayer()
let gradientLayer = CAGradientLayer()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .clear
layer.addSublayer(gradientLayer)
gradientLayer.mask = shapeLayer
gradientLayer.colors = [UIColor.blue.cgColor, UIColor.white.cgColor, UIColor.white.cgColor]
gradientLayer.type = .conic
gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 0.4, y: 0)
gradientLayer.locations = [0, 0.75, 1]
gradientLayer.backgroundColor = UIColor.clear.cgColor
shapeLayer.fillColor = nil
shapeLayer.strokeColor = CGColor(gray: 0, alpha: 1)
shapeLayer.lineWidth = 5
shapeLayer.lineCap = .round
let animation = CABasicAnimation(keyPath: "transform.rotation")
animation.fromValue = CGFloat.pi * 2
animation.toValue = 0
animation.duration = 1
animation.repeatCount = .greatestFiniteMagnitude
layer.add(animation, forKey: "transform.rotation")
}
override func layoutSubviews() {
super.layoutSubviews()
gradientLayer.frame = bounds
shapeLayer.frame = bounds
let path = UIBezierPath(
arcCenter: .init(x: bounds.midX, y: bounds.midY),
radius: bounds.width / 2 - 20,
startAngle: 1.55 * .pi, endAngle: .pi, clockwise: true)
shapeLayer.path = path.cgPath
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
用途:
class MyViewController: UIViewController {
override func viewDidLoad() {
let progress = FadingProgressView(frame: CGRect(x: 200, y: 200, width: 100, height: 100))
view.addSubview(progress)
}
}