iOS自定义UIButton点击动画特效
时间:2021-03-14 09:48:07|栏目:iOS代码|点击: 次
借鉴相关资料,整理了一个很有意思的button动画效果,iOS自定义UIButton点击动画特效
先看一下效果图:
下面贴上代码:
ViewController:
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @end #import "ViewController.h" #import "HWButton.h" #define mainW [UIScreen mainScreen].bounds.size.width #define mainH [UIScreen mainScreen].bounds.size.height @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor blackColor]; //创建控件 [self creatButton]; } - (void)creatButton { HWButton *button = [[HWButton alloc] initWithFrame:CGRectMake(mainW * 0.5 - 60, mainH - 100, 120, 72) maxLeft:100 maxRight:100 maxHeight:300]; [button setImage:[UIImage imageNamed:@"button"] forState:UIControlStateNormal]; button.images = @[[UIImage imageNamed:@"Circle 1"], [UIImage imageNamed:@"Circle 2"], [UIImage imageNamed:@"Circle 3"], [UIImage imageNamed:@"Hero"]]; button.duration = 10; [button addTarget:self action:@selector(buttonOnClick:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; } - (void)buttonOnClick:(HWButton *)btn { [btn generateBubbleInRandom]; } @end
HWButton:
#import <UIKit/UIKit.h> @interface HWButton : UIButton @property (nonatomic, assign) CGFloat maxLeft; @property (nonatomic, assign) CGFloat maxRight; @property (nonatomic, assign) CGFloat maxHeight; @property (nonatomic, assign) CGFloat duration; @property (nonatomic, strong) NSArray *images; - (instancetype)initWithFrame:(CGRect)frame maxLeft:(CGFloat)maxLeft maxRight:(CGFloat)maxRight maxHeight:(CGFloat)maxHeight; - (void)generateBubbleWithImage:(UIImage *)image; - (void)generateBubbleInRandom; @end #import "HWButton.h" @implementation HWButton { CGPoint _startPoint; CGFloat _maxWidth; NSMutableSet *_recyclePool; NSMutableArray *_array; } - (instancetype)initWithFrame:(CGRect)frame maxLeft:(CGFloat)maxLeft maxRight:(CGFloat)maxRight maxHeight:(CGFloat)maxHeight { self = [super initWithFrame:frame]; if (self) { _maxHeight = maxHeight; _maxLeft = maxLeft; _maxRight = maxRight; [self initData]; } return self; } - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { [self initData]; } return self; } - (void)initData { _array = @[].mutableCopy; _recyclePool = [NSMutableSet set]; } - (void)generateBubbleInRandom { CALayer *layer; if (_recyclePool.count > 0) { layer = [_recyclePool anyObject]; [_recyclePool removeObject:layer]; }else { UIImage *image = self.images[arc4random() % self.images.count]; layer = [self createLayerWithImage:image]; } [self.layer addSublayer:layer]; [self generateBubbleWithCAlayer:layer]; } - (void)generateBubbleWithImage:(UIImage *)image { CALayer *layer = [self createLayerWithImage:image]; [self.layer addSublayer:layer]; [self generateBubbleWithCAlayer:layer]; } - (void)generateBubbleWithCAlayer:(CALayer *)layer { _maxWidth = _maxLeft + _maxRight + self.bounds.size.width; _startPoint = CGPointMake(self.frame.size.width / 2, 0); CGPoint endPoint = CGPointMake(_maxWidth * [self randomFloat] - _maxLeft, -_maxHeight); CGPoint controlPoint1 = CGPointMake(_maxWidth * [self randomFloat] - _maxLeft, -_maxHeight * 0.2); CGPoint controlPoint2 = CGPointMake(_maxWidth * [self randomFloat] - _maxLeft, -_maxHeight * 0.6); CGMutablePathRef curvedPath = CGPathCreateMutable(); CGPathMoveToPoint(curvedPath, NULL, _startPoint.x, _startPoint.y); CGPathAddCurveToPoint(curvedPath, NULL, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y); CAKeyframeAnimation *keyFrame = [CAKeyframeAnimation animation]; keyFrame.keyPath = @"position"; keyFrame.path = CFAutorelease(curvedPath); keyFrame.duration = self.duration; keyFrame.calculationMode = kCAAnimationPaced; [layer addAnimation:keyFrame forKey:@"keyframe"]; CABasicAnimation *scale = [CABasicAnimation animation]; scale.keyPath = @"transform.scale"; scale.toValue = @1; scale.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 0.1)]; scale.duration = 0.5; CABasicAnimation *alpha = [CABasicAnimation animation]; alpha.keyPath = @"opacity"; alpha.fromValue = @1; alpha.toValue = @0.1; alpha.duration = self.duration * 0.4; alpha.beginTime = self.duration - alpha.duration; CAAnimationGroup *group = [CAAnimationGroup animation]; group.animations = @[keyFrame, scale, alpha]; group.duration = self.duration; group.delegate = self; group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; group.fillMode = kCAFillModeForwards; group.removedOnCompletion = NO; [layer addAnimation:group forKey:@"group"]; [_array addObject:layer]; } - (CGFloat)randomFloat { return (arc4random() % 100)/100.0f; } - (CALayer *)createLayerWithImage:(UIImage *)image { CGFloat scale = [UIScreen mainScreen].scale; CALayer *layer = [CALayer layer]; layer.frame = CGRectMake(0, 0, image.size.width / scale, image.size.height / scale); layer.contents = (__bridge id)image.CGImage;; return layer; } - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { if (flag) { CALayer *layer = [_array firstObject]; [layer removeAllAnimations]; [layer removeFromSuperlayer]; [_array removeObject:layer]; [_recyclePool addObject:layer]; } } @end