ios – Gradient animation isn’t working correctly


As an alternative of attempting to animate the gradient colours and areas, one other method is to rotate the CAGradientLayer.

So, if we begin with a plain view:

enter image description here

we will add a CAGradientLayer as a sublayer — right here, it has solely a single 1/2 alpha colour so we will simply see the framing:

enter image description here

As a result of we will probably be rotating that layer, we set that layer’s body to be bigger than the view so it’ll fully cowl it:

enter image description here enter image description here

Subsequent, we set the gradient layer’s colours to clear, white, clear:

enter image description here enter image description here

enter image description here enter image description here

and at last, apply a form layer masks to the view:

enter image description here enter image description here

enter image description here enter image description here

This is the way it appears to be like on a black background:

enter image description here

And listed here are some animated variations (too huge to embed right here): https://imgur.com/a/JXgyT7b

Right here is a few instance code for that:

// couple helpers for CGRect
extension CGRect {
    public var heart: CGPoint { return CGPoint(x: midX, y: midY) }
    public var diagonalExtent: CGFloat { return hypot(width, top) }
}

// instance view
class AnimatedGradientBorderedView: UIView {

    public var lineWidth: CGFloat = 1.0 { didSet { mskLayer.lineWidth = lineWidth } }
    public var cornerRadius: CGFloat = 16.0 { didSet { setNeedsLayout() } }
    
    non-public let gradLayer = CAGradientLayer()
    non-public let mskLayer = CAShapeLayer()

    override init(body: CGRect) {
        tremendous.init(body: body)
        commonInit()
    }
    required init?(coder aDecoder: NSCoder) {
        tremendous.init(coder:aDecoder)
        commonInit()
    }
    
    func commonInit() {

        gradLayer.colours = [UIColor.clear.cgColor, UIColor.white.cgColor, UIColor.clear.cgColor]
        layer.addSublayer(gradLayer)

        mskLayer.fillColor = UIColor.clear.cgColor
        // any opaque colour
        mskLayer.strokeColor = UIColor.black.cgColor
        mskLayer.lineWidth = lineWidth
        
    }
    
    override func layoutSubviews() {
        tremendous.layoutSubviews()

        // we'd like the gradient layer body to cowl the whole view
        //  when it rotates, so we make it a sq. with width/top
        //  equal to the diagonal dimension of self (plus just a bit "padding")
        let diag: CGFloat = bounds.diagonalExtent + 2.0
        gradLayer.body = bounds.insetBy(dx: -(diag - bounds.width) * 0.5, dy: -(diag - bounds.top) * 0.5)
        
        // rounded-corners masks path, inset by lineWidth so it's fully inside self
        mskLayer.path = UIBezierPath(roundedRect: bounds.insetBy(dx: lineWidth, dy: lineWidth), cornerRadius: cornerRadius).cgPath
        layer.masks = mskLayer

        doAnim()
    }
    
    func doAnim() {
        
        // rotate the masks layer
        let rotateAnimation = CABasicAnimation(keyPath: "rework.rotation")
        rotateAnimation.fromValue = 0.0
        rotateAnimation.toValue = CGFloat(Double.pi * 2)
        rotateAnimation.isRemovedOnCompletion = false
        // alter rotation velocity as desired
        rotateAnimation.length = 8.0
        rotateAnimation.repeatCount=Float.infinity
        gradLayer.add(rotateAnimation, forKey: nil)
        
    }
    
}

// easy instance view controller
class MyViewController: UIViewController {
    
    let testView = AnimatedGradientBorderedView()
    
    override func viewDidLoad() {
        tremendous.viewDidLoad()
        
        testView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(testView)
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            
            testView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 34.0),
            testView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -34.0),
            testView.heightAnchor.constraint(equalToConstant: 492.0),
            testView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            
        ])
        
        view.backgroundColor = .black
        testView.backgroundColor = .clear
        
    }
    
}

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles