iOS自定义UIButton点击动画特效

借鉴相关资料,整理了一个很有意思的button动画效果,iOS自定义UIButton点击动画特效

先看一下效果图:

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,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,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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...