├── LICENSE ├── README.md ├── YGPulseView ├── UIView+YGPulseView.h └── UIView+YGPulseView.m └── animation.gif /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 George Ymydykov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # YGPulseView 2 | 3 | YGPulseView is Objective-C Category for making pulsing animation with UIView: 4 | 5 | ![alt tag](https://raw.githubusercontent.com/YGeorge/YGPulseView/master/animation.gif) 6 | 7 | ## How to use: 8 | 9 | ```obj-c 10 | 11 | - (void)viewDidLoad { 12 | [super viewDidLoad]; 13 | self.plusView.layer.cornerRadius = 30; 14 | } 15 | 16 | - (void)viewWillAppear:(BOOL)animated { 17 | [super viewWillAppear:animated]; 18 | [self.plusView startPulseWithColor:[UIColor greenColor] animation:YGPulseViewAnimationTypeRadarPulsing]; 19 | } 20 | 21 | ``` 22 | -------------------------------------------------------------------------------- /YGPulseView/UIView+YGPulseView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+YGPulseView.h 3 | // YGPulseView 4 | // 5 | // Created by YGeorge on 22/11/2016. 6 | // Copyright (c) 2016 YGeorge. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | typedef NS_ENUM(NSUInteger, YGPulseViewAnimationType) { 14 | YGPulseViewAnimationTypeRegularPulsing, 15 | YGPulseViewAnimationTypeRadarPulsing 16 | }; 17 | 18 | @interface UIView (YGPulseView) 19 | 20 | - (void)startPulseWithColor:(UIColor *)color; 21 | 22 | - (void)startPulseWithColor:(UIColor *)color animation:(YGPulseViewAnimationType)animationType; 23 | 24 | - (void)startPulseWithColor:(UIColor *)color scaleFrom:(CGFloat)initialScale to:(CGFloat)finishScale frequency:(CGFloat)frequency opacity:(CGFloat)opacity animation:(YGPulseViewAnimationType)animationType; 25 | 26 | - (void)stopPulse; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /YGPulseView/UIView+YGPulseView.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+YGPulseView.m 3 | // YGPulseView 4 | // 5 | // Created by YGeorge on 22/11/2016. 6 | // Copyright (c) 2016 YGeorge. All rights reserved. 7 | // 8 | 9 | #import "UIView+YGPulseView.h" 10 | 11 | NSString *const YGPulseKey = @"YGPulseKey"; 12 | NSString *const YGRadarKey = @"YGRadarKey"; 13 | NSString *const YGLayerName = @"YGLayerName"; 14 | 15 | @implementation UIView (YGPulseView) 16 | 17 | - (void)startPulseWithColor:(UIColor *)color { 18 | [self startPulseWithColor:color scaleFrom:1.2f to:1.4f frequency:1.0f opacity:0.7f animation:YGPulseViewAnimationTypeRegularPulsing]; 19 | } 20 | 21 | - (void)startPulseWithColor:(UIColor *)color animation:(YGPulseViewAnimationType)animationType { 22 | CGFloat frequency = animationType == YGPulseViewAnimationTypeRadarPulsing ? 1.5f : 1.0f; 23 | CGFloat startScale = animationType == YGPulseViewAnimationTypeRadarPulsing ? 1.0f : 1.2f; 24 | [self startPulseWithColor:color scaleFrom:startScale to:1.4f frequency:frequency opacity:0.7f animation:animationType]; 25 | } 26 | 27 | - (void)startPulseWithColor:(UIColor *)color scaleFrom:(CGFloat)initialScale to:(CGFloat)finishScale frequency:(CGFloat)frequency opacity:(CGFloat)opacity animation:(YGPulseViewAnimationType)animationType { 28 | CALayer *externalBorder = [CALayer layer]; 29 | externalBorder.frame = self.frame; 30 | externalBorder.cornerRadius = self.layer.cornerRadius; 31 | externalBorder.backgroundColor = color.CGColor; 32 | externalBorder.opacity = opacity; 33 | externalBorder.name = YGLayerName; 34 | self.layer.masksToBounds = NO; 35 | [self.layer.superlayer insertSublayer:externalBorder below:self.layer]; 36 | 37 | CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 38 | scaleAnimation.fromValue = @(initialScale); 39 | scaleAnimation.toValue = @(finishScale); 40 | scaleAnimation.duration = frequency; 41 | scaleAnimation.autoreverses = animationType == YGPulseViewAnimationTypeRegularPulsing; 42 | scaleAnimation.repeatCount = INT32_MAX; 43 | [externalBorder addAnimation:scaleAnimation forKey:YGPulseKey]; 44 | 45 | if (animationType == YGPulseViewAnimationTypeRadarPulsing) { 46 | CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 47 | opacityAnimation.fromValue = @(opacity); 48 | opacityAnimation.toValue = @(0.0); 49 | opacityAnimation.duration = frequency; 50 | opacityAnimation.autoreverses = NO; 51 | opacityAnimation.repeatCount = INT32_MAX; 52 | [externalBorder addAnimation:opacityAnimation forKey:YGRadarKey]; 53 | } 54 | } 55 | 56 | - (void)stopPulse { 57 | [self.layer removeAnimationForKey:YGPulseKey]; 58 | [self.layer removeAnimationForKey:YGRadarKey]; 59 | CALayer *externalBorderLayer = [self externalBorderLayer]; 60 | if (externalBorderLayer) { 61 | [externalBorderLayer removeFromSuperlayer]; 62 | } 63 | } 64 | 65 | - (CALayer *)externalBorderLayer { 66 | for (CALayer *layer in self.layer.superlayer.sublayers) { 67 | if ([layer.name isEqualToString:YGLayerName]) { 68 | return layer; 69 | } 70 | } 71 | return nil; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YGeorge/YGPulseView/321793621df7b6f47ecdfba10981fc01240aeb5c/animation.gif --------------------------------------------------------------------------------