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

.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. SpringMVC+Mybatis+Spring整合

    Maven引入需要的JAR包 pom.xml <properties> <!-- spring版本号 --> <spring.version>4.0.2.RELEA ...

  2. H5离线存储

    如何使用 首先,我们建立一个html文件,类似这样: <!DOCTYPE html> <html lang="en" manifest="manifes ...

  3. 如何判断Javascript对象是否存在

    Javascript语言的设计不够严谨,很多地方一不小心就会出错. 举例来说,请考虑以下情况. 现在,我们要判断一个全局对象myObj是否存在,如果不存在,就对它进行声明.用自然语言描述的算法如下: ...

  4. javac 导入第三方jar包

    如果是导入一个包,只需要 javac -classpath xxx/xxx/xxx.jar xxx.java 即可 如果有多个包,windows下用分号隔开,Lunix下用冒号隔开即可.

  5. for(String s:v)

    s是遍历后赋值的变量,v是要遍历的list.可以通过以下语句进行测试: List<String> v=new ArrayList(); v.add("one"); v. ...

  6. rpm 软件安装

    安装 vi 软件 rpm q查询 a全部软件 e 卸载 i 安装 v 显示进度 h 以#显示 首先确定软件时候安装 rpm 实现软件的安装 卸载 升级 查询等 1)查询是否已经安装过 rpm -qa ...

  7. 51nod1305 Pairwise Sum and Divide

    题目链接:51nod 1305 Pairwise Sum and Divide 看完题我想都没想就直接暴力做了,AC后突然就反应过来了... Floor( (a+b)/(a*b) )=Floor( ( ...

  8. python 执行execute遇到的问题

    1.如下方式去查询无法查询出结果,但直接在数据库查询中去查询是能查询到结果的,郁闷中,花了很久的时间才知道原来是双引号导致的 把:name="%s" 中的%s前后的双引号去掉就对了 ...

  9. NFA引擎匹配原理

    1       为什么要了解引擎匹配原理 一个个音符杂乱无章的组合在一起,弹奏出的或许就是噪音,同样的音符经过作曲家的手,就可以谱出非常动听的乐曲,一个演奏者同样可以照着乐谱奏出动听的乐曲,但他/她或 ...

  10. Swift 05.Block

    Swift的函数用法还真是灵活.但是个人感觉更灵活的还是闭包. swift闭包的概念大抵相当于OC的block的概念.如果对于block的理解很透彻的话,闭包的原理性的东西还是很好理解的. 剩下的就是 ...