Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIButton Heartbeat Animation

I've created a heart beat animation for a UIButton. However, there is no way to stop this animation as it's an endless code loop. After tinkering with numerous UIView animation code blocks I've been unable to get UIViewAnimationOptions.Repeat to produce what I need. If I could do that I could simply button.layer.removeAllAnimations() to remove the animations. What is a way to write this that allows for removal of the animation? I'm thinking a timer possibly but that could be kind of messy with multiple animations going on.

func heartBeatAnimation(button: UIButton) {

    button.userInteractionEnabled = true
    button.enabled = true

    func animation1() {

        UIView.animateWithDuration(0.5, delay: 0.0, options: [], animations: { () -> Void in

            button.transform = CGAffineTransformMakeScale(2.0, 2.0)
            button.transform = CGAffineTransformIdentity

        }, completion: nil)

        UIView.animateWithDuration(0.5, delay: 0.5, options: [], animations: { () -> Void in

            button.transform = CGAffineTransformMakeScale(2.0, 2.0)
            button.transform = CGAffineTransformIdentity

            }) { (Bool) -> Void in

                delay(2.0, closure: { () -> () in

                    animation2()

                })       
        }
    }

    func animation2() {

        UIView.animateWithDuration(0.5, delay: 0.0, options: [], animations: { () -> Void in

            button.transform = CGAffineTransformMakeScale(2.0, 2.0)
            button.transform = CGAffineTransformIdentity

            }, completion: nil)

        UIView.animateWithDuration(0.5, delay: 0.5, options: [], animations: { () -> Void in

            button.transform = CGAffineTransformMakeScale(2.0, 2.0)
            button.transform = CGAffineTransformIdentity

            }) { (Bool) -> Void in

                delay(2.0, closure: { () -> () in

                    animation1()

                })
        }
    }

    animation1()

}
like image 641
Phil Andrews Avatar asked Jan 11 '16 19:01

Phil Andrews


3 Answers

This works perfectly. The damping and spring need to be tweaked a little bit but this solves the problem. removeAllAnimations() clears the animation and returns the button to it's normal state.

button.userInteractionEnabled = true
button.enabled = true

let pulse1 = CASpringAnimation(keyPath: "transform.scale")
pulse1.duration = 0.6
pulse1.fromValue = 1.0
pulse1.toValue = 1.12
pulse1.autoreverses = true
pulse1.repeatCount = 1
pulse1.initialVelocity = 0.5
pulse1.damping = 0.8

let animationGroup = CAAnimationGroup()
animationGroup.duration = 2.7
animationGroup.repeatCount = 1000
animationGroup.animations = [pulse1]

button.layer.addAnimation(animationGroup, forKey: "pulse")

This post was very helpful: CAKeyframeAnimation delay before repeating

like image 165
Phil Andrews Avatar answered Nov 14 '22 19:11

Phil Andrews


Swift 5 code, works without the pause between pulses:

    let pulse = CASpringAnimation(keyPath: "transform.scale")
    pulse.duration = 0.4
    pulse.fromValue = 1.0
    pulse.toValue = 1.12
    pulse.autoreverses = true
    pulse.repeatCount = .infinity
    pulse.initialVelocity = 0.5
    pulse.damping = 0.8
    switchButton.layer.add(pulse, forKey: nil)
like image 11
S.S.D Avatar answered Nov 14 '22 21:11

S.S.D


I created something like this:

    let animation = CAKeyframeAnimation(keyPath: "transform.scale")

    animation.values = [1.0, 1.2, 1.0]
    animation.keyTimes = [0, 0.5, 1]
    animation.duration = 1.0
    animation.repeatCount = Float.infinity
    layer.add(animation, forKey: "pulse")
like image 6
Arek Avatar answered Nov 14 '22 19:11

Arek