I need help with making an animation that runs a gradient trough the borders of a view, as shown in this GIF:
Any ideas how to go about it in Swift?
Thanks!
Solution
Here’s my solution:
- Use an animated gradient layer for the base view
- Add an overlaying white view (with inset) to cover up the center of the gradient
- As MadProgrammer said, you can set the gradient’s
startPoint
andendPoint
at an angle, to get it to go around the corners
class BorderShimmerView : UIView {
/// allow gradient layer to resize automatically
override class var layerClass: AnyClass { return CAGradientLayer.self }
/// boilerplate UIView initializers
init() {
super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
/// set up everything
func commonInit() {
let overlayView = UIView() /// add a view overlaid on the gradient view
overlayView.backgroundColor = .white
overlayView.frame = bounds.insetBy(dx: 3, dy: 3) /// appears like a border
overlayView.autoresizingMask = [.flexibleWidth, .flexibleHeight] /// allow resizing
self.addSubview(overlayView)
let gradientLayer = self.layer as! CAGradientLayer
gradientLayer.locations = [0, 0.45, 0.55, 1] /// adjust this to change the colors' spacing
gradientLayer.colors = [
UIColor.white.cgColor,
UIColor.yellow.cgColor, /// yellow + orange for gold effect
UIColor.orange.cgColor,
UIColor.white.cgColor
]
let startPointAnimation = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.startPoint))
startPointAnimation.fromValue = CGPoint(x: 2, y: -1) /// extreme top right
startPointAnimation.toValue = CGPoint(x: 0, y: 1) /// bottom left
let endPointAnimation = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.endPoint))
endPointAnimation.fromValue = CGPoint(x: 1, y: 0) /// top right
endPointAnimation.toValue = CGPoint(x: -1, y: 2) /// extreme bottom left
let animationGroup = CAAnimationGroup() /// group animations together
animationGroup.animations = [startPointAnimation, endPointAnimation]
animationGroup.duration = 2
animationGroup.repeatCount = .infinity /// repeat animation infinitely
gradientLayer.add(animationGroup, forKey: nil)
}
}
Usage:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let shimmerView = BorderShimmerView()
shimmerView.frame = CGRect(x: 50, y: 50, width: 300, height: 300)
view.addSubview(shimmerView)
}
}
Result: