90

I would like to have some kind of pulse animation (infinite loop "scale in - scale out") on a UIButton so it gets users' attention immediately.

I saw this link How to create a pulse effect using -webkit-animation - outward rings but I was wondering if there was any way to do this only using native framework?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Johann
  • 12,158
  • 11
  • 62
  • 89

4 Answers4

200
CABasicAnimation *theAnimation;

theAnimation=[CABasicAnimation animationWithKeyPath:@"opacity"];
theAnimation.duration=1.0;
theAnimation.repeatCount=HUGE_VALF;
theAnimation.autoreverses=YES;
theAnimation.fromValue=[NSNumber numberWithFloat:1.0];
theAnimation.toValue=[NSNumber numberWithFloat:0.0];
[theLayer addAnimation:theAnimation forKey:@"animateOpacity"]; //myButton.layer instead of

Swift

let pulseAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.opacity))
pulseAnimation.duration = 1
pulseAnimation.fromValue = 0
pulseAnimation.toValue = 1
pulseAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
pulseAnimation.autoreverses = true
pulseAnimation.repeatCount = .greatestFiniteMagnitude
view.layer.add(pulseAnimation, forKey: "animateOpacity")

See the article "Animating Layer Content"

Cœur
  • 37,241
  • 25
  • 195
  • 267
beryllium
  • 29,669
  • 15
  • 106
  • 125
  • 1
    Thanks for your answer! I have to say I'm a bit stuck though. I'm not familiar at all with CALayer and I'm not sure how to link it with my UIButton. Plus your code looks like it's changing opacity, not scale. – Johann Nov 10 '11 at 17:21
  • 8
    okay). 'Pulse animating' is a term usually applied to flicker effect - as said in example in that link. Now i re-read your question and understand what you want. At first, every view has own layer. If QartzCore framework is added to project then just type `myView.layer` to access it. You can animate layers with Core Animation. For scale transformation you can use this approach: [Key Path Support for Structure Fields](http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/KVCAdditions.html#//apple_ref/doc/uid/TP40005299-SW6) – beryllium Nov 10 '11 at 17:35
  • 7
    Fantastic! Using @"transform.scale" instead of @"opacity" works like a charm. Thanks a lot! – Johann Nov 10 '11 at 17:54
  • 2
    If you don't already have it, you need to add `#import ` in order to get all the definitions for CALayers. – progrmr Jun 21 '13 at 18:28
  • UGH! Don't edit 3 year old answers that are out of date unless you're updating the actual answer to the correct modern version. Adding spaces is not updating it. Especially not to resurrect it after 3 years. – Fogmeister Mar 10 '14 at 17:05
  • If you'd like to add a nice animation curves, use the following snippet (taken from http://www.developerfeed.com/how-create-pulse-effect-uiviews-using-core-animation-ios): `theAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];` – rizzes Nov 25 '14 at 18:37
  • Say we add this to multiple views but only want one to pulse at one time, once the animation is added, is there a on/off definition...OTHER than .removeAllAnimation or .removeAnimationForKey. Or are we forced to remove then reAdd the pulseAnimation?......and whats the overhead if we just leave this animation running constantly. – Chameleon Jun 19 '15 at 05:17
  • keypath is appstore safe..? – amar Dec 01 '16 at 08:35
  • Just to be completely precise - FLT_MAX is big but finite value. – Yakiv Kovalskyi Jan 20 '17 at 13:19
  • combining it with below answer makes pulse effect this one only makes opacity you need to add transform aswell – Lekve Mar 04 '17 at 22:45
  • hello. how can i apply to GMSMarker? – kemdo Aug 07 '18 at 08:39
32

Here is the swift code for it ;)

let pulseAnimation = CABasicAnimation(keyPath: "transform.scale")
pulseAnimation.duration = 1.0
pulseAnimation.fromValue = NSNumber(value: 0.0)
pulseAnimation.toValue = NSNumber(value: 1.0)
pulseAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
pulseAnimation.autoreverses = true
pulseAnimation.repeatCount = .greatestFiniteMagnitude
self.view.layer.add(pulseAnimation, forKey: nil)
pkamb
  • 33,281
  • 23
  • 160
  • 191
Ravi Sharma
  • 578
  • 4
  • 13
  • 2
    What's up with all the semi-colons? ;) – Christian May 24 '16 at 18:09
  • @Christian the semi colon sets the type of the pulseAnimation constant. It's not necessary to use but it does tend to increase code clarity when the right hand side of an assignment doesn't make it obvious what type it will assign. – Scott Chow Jan 16 '18 at 22:29
  • @ScottChow I guess you are talking about the colon. My comment was a joke to the original answer, since there is no need for semicolons with Swift. Guess it was not that obvious now when the answer has been edited a lot :) – Christian Jan 17 '18 at 12:10
  • make sure to add a fromValue – Kev Wats Oct 11 '20 at 00:55
10

The swift code is missing a fromValue, I had to add it in order to get it working.

pulseAnimation.fromValue = NSNumber(value: 0.0)

Also forKey should be set, otherwise removeAnimation doesn't work.

self.view.layer.addAnimation(pulseAnimation, forKey: "layerAnimation")
José
  • 3,112
  • 1
  • 29
  • 42
Bassebus
  • 682
  • 1
  • 6
  • 14
4
func animationScaleEffect(view:UIView,animationTime:Float)
{
    UIView.animateWithDuration(NSTimeInterval(animationTime), animations: {

        view.transform = CGAffineTransformMakeScale(0.6, 0.6)

        },completion:{completion in
            UIView.animateWithDuration(NSTimeInterval(animationTime), animations: { () -> Void in

                view.transform = CGAffineTransformMakeScale(1, 1)
            })
    })

}


@IBOutlet weak var perform: UIButton!

@IBAction func prefo(sender: AnyObject) {
    self.animationScaleEffect(perform, animationTime: 0.7)
}