O código abaixo mostra o problema:
import UIKit
import SnapKit
class ViewController: UIViewController {
let animatedBorderView = AnimatedGradientBorderView()
override func viewDidLoad() {
super.viewDidLoad()
animatedBorderView.layer.cornerRadius = 20
animatedBorderView.clipsToBounds = true
view.addSubview(animatedBorderView)
animatedBorderView.snp.makeConstraints { make in
make.center.equalToSuperview()
make.size.equalTo(400)
}
}
}
class AnimatedGradientBorderView: UIView {
private let gradientLayer = CAGradientLayer()
private let shapeLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
setupLayers()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupLayers()
}
private func setupLayers() {
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 1)
gradientLayer.colors = [
UIColor.systemRed.cgColor,
UIColor.systemYellow.cgColor,
UIColor.systemGreen.cgColor,
]
gradientLayer.locations = [0, 0.3, 0.6, 1]
layer.addSublayer(gradientLayer)
shapeLayer.lineWidth = 5
shapeLayer.fillColor = nil
shapeLayer.strokeColor = UIColor.black.cgColor
gradientLayer.mask = shapeLayer
startAnimating()
}
override func layoutSubviews() {
super.layoutSubviews()
gradientLayer.frame = bounds
let path = UIBezierPath(roundedRect: bounds.insetBy(dx: shapeLayer.lineWidth / 2, dy: shapeLayer.lineWidth / 2), cornerRadius: layer.cornerRadius)
shapeLayer.path = path.cgPath
}
private func startAnimating() {
let animation = CABasicAnimation(keyPath: "locations")
animation.fromValue = [0, 0.2, 0.4, 0.6]
animation.toValue = [0.4, 0.6, 0.8, 1]
animation.duration = 2.0
animation.repeatCount = .infinity
animation.autoreverses = false
gradientLayer.add(animation, forKey: "animateLocations")
}
}
Isso produz a animação abaixo:
Observe que defini autoreverses
como falso porque não quero que ele reverta ao repetir para infinity
. No entanto, como consequência disso, o problema é que, após o duration
, ele reinicia no original location
. Isso causa um salto repentino na borda do gradiente móvel.
Como posso fazer com que ele continue se movendo para sempre na mesma direção sem precisar reiniciar?