How to animate a border shimmer in swift?

Total
0
Shares

I need help with making an animation that runs a gradient trough the borders of a view, as shown in this GIF:

border animation

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 and endPoint 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:

Gold shimmer animating on border

Leave a Reply

Your email address will not be published. Required fields are marked *