One strategy is to masks a CAGradientLayer
with a CAShapeLayer
. The form layer ought to have an arc as its path
, and a lineCap
of .spherical
.
class FadingProgressView: UIView {
let shapeLayer = CAShapeLayer()
let gradientLayer = CAGradientLayer()
override init(body: CGRect) {
tremendous.init(body: body)
backgroundColor = .clear
layer.addSublayer(gradientLayer)
gradientLayer.masks = shapeLayer
gradientLayer.colours = [UIColor.blue.cgColor, UIColor.white.cgColor, UIColor.white.cgColor]
gradientLayer.kind = .conic
gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 0.4, y: 0)
gradientLayer.places = [0, 0.75, 1]
gradientLayer.backgroundColor = UIColor.clear.cgColor
shapeLayer.fillColor = nil
shapeLayer.strokeColor = CGColor(grey: 0, alpha: 1)
shapeLayer.lineWidth = 5
shapeLayer.lineCap = .spherical
let animation = CABasicAnimation(keyPath: "remodel.rotation")
animation.fromValue = CGFloat.pi * 2
animation.toValue = 0
animation.length = 1
animation.repeatCount = .greatestFiniteMagnitude
layer.add(animation, forKey: "remodel.rotation")
}
override func layoutSubviews() {
tremendous.layoutSubviews()
gradientLayer.body = bounds
shapeLayer.body = 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 applied")
}
}
Utilization:
class MyViewController: UIViewController {
override func viewDidLoad() {
let progress = FadingProgressView(body: CGRect(x: 200, y: 200, width: 100, peak: 100))
view.addSubview(progress)
}
}