• iOS仿直播带有气泡动画的UIButton


    现在直播软件确实很火,因为需要就写了一个带有动画气泡的按钮,代码中的部分动画有参考到其他童鞋,在这里万分感谢! 

    .h文件

    @interface YYBubbleButton : UIButton
    
    @property (nonatomic, assign)CGFloat maxLeft;//漂浮左边最大距离
    @property (nonatomic, assign)CGFloat maxRight;//漂浮右边最大距离
    @property (nonatomic, assign)CGFloat maxHeight;//漂浮最高距离
    @property (nonatomic, assign)CGFloat duration;//一组图片播放完的时间
    @property (nonatomic, copy)NSArray *images;//图片数组
    
    
    //init
    -(instancetype)initWithFrame:(CGRect)frame
                    folatMaxLeft:(CGFloat)maxLeft
                    folatMaxRight:(CGFloat)maxRight
                    folatMaxHeight:(CGFloat)maxHeight;
    
    //开始动画
    -(void)startBubble;
    
    @end
    

     .m文件

    @interface YYBubbleButton()
    @property(nonatomic,strong)NSTimer *timer;
    
    @property(nonatomic,assign)CGFloat maxWidth;
    
    @property(nonatomic,assign)CGPoint startPoint;
    
    @property(nonatomic,strong) NSMutableArray *layerArray;
    @end
    
    
    @implementation YYBubbleButton
    
    
    //初始化
    -(instancetype)initWithFrame:(CGRect)frame folatMaxLeft:(CGFloat)maxLeft folatMaxRight:(CGFloat)maxRight folatMaxHeight:(CGFloat)maxHeight
    {
        self = [super initWithFrame:frame];
        if(self)
        {
            _maxLeft = maxLeft;
            _maxRight = maxRight;
            _maxHeight = maxHeight;
            _layerArray = [NSMutableArray array];
        }
        return self;
    }
    //外部方法 开始气泡
    -(void)startBubble
    {
        self.timer = [NSTimer scheduledTimerWithTimeInterval:self.duration/self.images.count target:self selector:@selector(generateBubble) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop]addTimer:self.timer forMode:UITrackingRunLoopMode];
    }
    
    -(void)generateBubble
    {
        CALayer *layer =[CALayer layer];;
        UIImage *image = self.images[arc4random() % self.images.count];
        
        layer = [self createLayerWithImage:image];
        [self.layer addSublayer:layer];
        [self generateBubbleByLayer:layer];
    }
    
    //创建带有Image的Layer
    - (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)generateBubbleByLayer:(CALayer*)layer
    {
        _maxWidth = _maxLeft + _maxRight;
        _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);
        UIBezierPath *path = [UIBezierPath bezierPathWithCGPath:curvedPath];
        //[path addCurveToPoint:endPoint controlPoint1:_startPoint controlPoint2:controlPoint1];
        
        CAKeyframeAnimation *keyFrame = [CAKeyframeAnimation animation];
        keyFrame.keyPath = @"position";
        keyFrame.path = path.CGPath;
        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"];
        
        [self.layerArray addObject:layer];
    }
    -(void)dealloc
    {
        [self.layerArray removeAllObjects];
    }
    
    -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
    {
        if (flag)
        {
            CALayer *layer = [self.layerArray firstObject];
            [layer removeAllAnimations];
            [layer removeFromSuperlayer];
            [self.layerArray removeObject:layer];
        }
        
    }
    - (CGFloat)randomFloat{
        return (arc4random() % 100)/100.0f;
    }
    

     调用方法很简单:

    @interface ViewController ()

    @property(nonatomic,strong)YYBubbleButton *button;

    @end

    @implementation ViewController

    - (void)viewDidLoad {

        [super viewDidLoad];

        self.button = [[YYBubbleButton alloc]initWithFrame:CGRectMake(150, 300, 50, 20) folatMaxLeft:50 folatMaxRight:50 folatMaxHeight:150];

        self.button.backgroundColor = [UIColor redColor];

        [self.button setTitle:@"点我" forState:UIControlStateNormal];

        self.button.images = @[[UIImage imageNamed:@"heart3"],[UIImage imageNamed:@"heart4"],[UIImage imageNamed:@"heart5"],[UIImage imageNamed:@"heart6"]];

        self.button.duration = 4.0;

        [self.view addSubview:self.button];

        [self.button startBubble];

    }

    注意:如果加载大量图片,不建议用imageNamed方法加载

  • 相关阅读:
    流式布局思想
    盒子的显隐
    高级布局 浮动 清浮动
    display总结 overflow知识
    边界圆角 盒模型布局 图片背景 精灵图
    io模型
    协程
    GIL 进程池与线程池
    守护进程 互斥锁 进程间通讯
    子进程
  • 原文地址:https://www.cnblogs.com/yy342901/p/5795935.html
Copyright © 2020-2023  润新知