Search code examples
swiftcabasicanimation

How to make an animation shadowOffset in Swift?


I wrote the code but I can not understand why it does not work...

func animate(vc: UIView) {
    vc.layer.shadowColor = #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1)
    vc.layer.shadowRadius = 5
    vc.layer.shadowOffset = CGSize(width: 0, height: 0)
    let animationX = CABasicAnimation()
    animationX.keyPath = "shadowOffset"
    animationX.fromValue = vc.layer.shadowOffset
    animationX.toValue = CGSize(width: 10, height: 10)
    animationX.duration = 1
    vc.layer.add(animationX, forKey: animationX.keyPath)
}

@IBAction func buttonTapped(_ sender: UIButton) {
  animate(vc: sender)
}

Does anyone know how this works?


Solution

  • Couple of things missing

    1. shadowPath
    2. shadowOpacity
            vc.layer.masksToBounds = false
            vc.layer.shadowColor = #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1)
            vc.layer.shadowRadius = 5
            vc.layer.shadowOffset = CGSize(width: 0, height: 0)
            vc.layer.shadowPath = UIBezierPath(rect: vc.bounds).cgPath
            vc.layer.shadowOpacity = 1.0
            let animationX = CABasicAnimation()
            animationX.keyPath = "shadowOffset"
            animationX.fromValue = vc.layer.shadowOffset
            animationX.toValue = CGSize(width: 10, height: 10)
            animationX.duration = 1
            vc.layer.add(animationX, forKey: animationX.keyPath)
    

    By default shadowOpacity is 0.

    Final O/P

    enter image description here

    EDIT:

    If you want shadow to persist in its position even after animation specify

    1. fillMode
    2. isRemovedOnCompletion

    final code will look like

    func animate(vc: UIView) {
            vc.layer.masksToBounds = false
            vc.layer.shadowColor = #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1)
            vc.layer.shadowRadius = 5
            vc.layer.shadowOffset = CGSize(width: 0, height: 0)
            vc.layer.shadowPath = UIBezierPath(rect: vc.bounds).cgPath
            vc.layer.shadowOpacity = 1.0
            let animationX = CABasicAnimation()
            animationX.keyPath = "shadowOffset"
            animationX.fromValue = vc.layer.shadowOffset
            animationX.toValue = CGSize(width: 10, height: 10)
            animationX.duration = 1
            animationX.fillMode = .forwards
            animationX.isRemovedOnCompletion = false
            vc.layer.add(animationX, forKey: animationX.keyPath)
        }
    

    Final O/P looks like:

    enter image description here