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

.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方法加载

iOS仿直播带有气泡动画的UIButton的更多相关文章

  1. iOS仿支付宝首页的刷新布局效果

    代码地址如下:http://www.demodashi.com/demo/12753.html XYAlipayRefreshDemo 运行效果 动画效果分析 1.UI需要变动,向上滑动的时候,顶部部 ...

  2. iOS开发UI篇—核心动画(转场动画和组动画)

    转自:http://www.cnblogs.com/wendingding/p/3801454.html iOS开发UI篇—核心动画(转场动画和组动画) 一.转场动画简单介绍 CAAnimation的 ...

  3. iOS开发UI篇—核心动画(关键帧动画)

    转自:http://www.cnblogs.com/wendingding/p/3801330.html iOS开发UI篇—核心动画(关键帧动画) 一.简单介绍 是CApropertyAnimatio ...

  4. 最近这么火的iOS视频直播

    快速集成iOS基于RTMP的视频推流 http://www.jianshu.com/p/8ea016b2720e iOS视频直播初窥:高仿<喵播APP> http://www.jiansh ...

  5. iOS CAEmitterLayer 实现粒子发射动画效果

    iOS CAEmitterLayer 实现粒子发射动画效果 效果图 代码已上传 GitHub:https://github.com/Silence-GitHub/CoreAnimationDemo 动 ...

  6. iOS仿支付宝首页效果

    代码地址如下:http://www.demodashi.com/demo/12776.html 首先看一下效果 状态栏红色是因为使用手机录屏的原因. 1.问题分析 1.导航栏A有两组控件,随着tabl ...

  7. iOS 仿看了吗应用、指南针测网速等常用工具、自定义弹出视图框架、图片裁剪、内容扩展等源码

    iOS精选源码 扩展内容的cell - folding-cell 一个近乎完整的可识别中国身份证信息的Demo 可自动快速... JPImageresizerView 仿微信的图片裁剪 带年月和至今以 ...

  8. jquery仿搜狐投票动画代码

    体验效果:http://hovertree.com/texiao/jquery/21/ 这是一款基于jquery实现的仿搜狐投票动画特效源码,运行该源码可见VS图标首先出现在中间位置,紧接着随着投票比 ...

  9. iOS开发UI篇—核心动画(UIView封装动画)

    iOS开发UI篇—核心动画(UIView封装动画) 一.UIView动画(首尾) 1.简单说明 UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画 ...

随机推荐

  1. (转载)SQL— CONCAT(字符串连接函数)

    有的时候,我们有需要将由不同栏位获得的资料串连在一起.每一种资料库都有提供方法来达到这个目的: MySQL: CONCAT() Oracle: CONCAT(), || SQL Server: + C ...

  2. 了解真实的『REM』手机屏幕适配

    rem 作为一个低调的长度单位,由于手机端网页的兴起,在屏幕适配中得到重用.使用 rem 前端开发者可以很方便的在各种屏幕尺寸下,通过等比缩放的方式达到设计图要求的效果. rem 的官方定义『The ...

  3. 解读浮动闭合最佳方案:clearfix

    .clear{clear:both;height:0;overflow:hidden;} 上诉办法是在需要清除浮动的地方加个div.clear或者br.clear,我们知道这样能解决基本清浮动问题. ...

  4. Android应用中MVP开发模式

    所谓MVP(Model-View-Presenter)模式.是将APP的结构分为三层: view - UI显示层 view 层主要负责: 提供UI交互 在presenter的控制下修改UI. 将业务事 ...

  5. Create and Install Timer Job in MOSS 2007

    Excute Timerjob public class TriggerLoadCacheTimerJob : SPJobDefinition { string ExceptionFlag = str ...

  6. guava学习--ComparisonChain

    转载:https://my.oschina.net/realfighter/blog/349824 在日常的工作中,我们经常需要对两个对象进行比较,以找出其中的异同, Java中提供了compare/ ...

  7. Swiper说明&&API手册 【中文手册Swiper】

     原文地址:http://www.cnblogs.com/scavengers/p/3760449.html 示例: <link rel="stylesheet" href= ...

  8. WHMCS成功安装和使用方法及添加支付宝,PayPal收款教程

    一.WHMCS安装前准备 1.WHMCS官网: 1.官方首页:http://www.whmcs.com/ 2.WHMCS需要安装在一个带MysqL数据库的PHP服务器中,一般地我们日常安装的VPS控制 ...

  9. Understanding the Internal Message Buffers of Storm

    Understanding the Internal Message Buffers of Storm Jun 21st, 2013 Table of Contents Internal messag ...

  10. 自定义带动画的Toast

    一.style样式: 1.  // 移动和透明渐变结合的动画 <style name="anim_view">        <item name="@ ...