现在直播软件确实很火,因为需要就写了一个带有动画气泡的按钮,代码中的部分动画有参考到其他童鞋,在这里万分感谢!
.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方法加载