如何在 swift 中为边框微光设置动画?

How to animate a border shimmer in swift?

我需要帮助制作一个在视图边界上运行渐变的动画,如此 GIF 所示:

有什么想法可以在 Swift 中实现吗?

谢谢!

这是我的解决方案:

  • 为基础视图使用动画渐变图层
  • 添加一个叠加的白色视图(带插图)以覆盖渐变的中心
  • 一样,您可以将渐变的startPointendPoint设置成一定角度,使其绕过拐角
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)
        
    }
}

用法:

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)
    }
}

结果: