CAKeyframeAnimation delay before repeating
By dumping the animations of Apple's MKUserLocationView
, I was able to see how they were doing it. Turns out that this is what CAAnimationGroup
is for. By encapsulating a 2 seconds animation into a 5 seconds animation group, you'll end up with a 2 seconds animation followed by a 3 seconds delay:
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];animationGroup.duration = 5;animationGroup.repeatCount = INFINITY;CAMediaTimingFunction *easeOut = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];CABasicAnimation *pulseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale.xy"];pulseAnimation.fromValue = @0.0;pulseAnimation.toValue = @1.0;pulseAnimation.duration = 2;pulseAnimation.timingFunction = easeOut;animationGroup.animations = @[pulseAnimation];[ringImageView.layer addAnimation:animationGroup forKey:@"pulse"];
samvermette's answer in Swift 3:
let animationGroup = CAAnimationGroup()animationGroup.duration = 5;animationGroup.repeatCount = .infinitylet easeOut = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)let pulseAnimation = CABasicAnimation(keyPath: "transform.scale.xy")pulseAnimation.fromValue = 0pulseAnimation.toValue = 1.0pulseAnimation.duration = 2pulseAnimation.timingFunction = easeOutanimationGroup.animations = [pulseAnimation]ringImageView.layer.add(animationGroup, forKey: "pulse")
Tested on Swift 4.2
Just implement the following extension and then you can get a nice pulse Animation on Any UI component
//MARK:- Pulse animationextension UIView { func applyPulse(_ apply: Bool = true) { if apply { let animation = CABasicAnimation(keyPath: "transform.scale") animation.toValue = 1.5 animation.duration = 0.8 animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) animation.autoreverses = true animation.repeatCount = Float.infinity self.layer.add(animation, forKey: "pulsing") } else { self.layer.removeAnimation(forKey: "pulsing") } }}
Usase:
To start
yourUiComponent.applyPulse()
To Stop
yourUiComponent.applyPulse(false)