#import <QuartzCore/QuartzCore.h>
@interface PulsatorLayer : CAReplicatorLayer
@property(nonatomic, assign) CGColorRef outColor;
@property(nonatomic, assign) CGColorRef inColor;
@property(nonatomic, assign) CGFloat animationDuration;
@property(nonatomic, assign) CGFloat animationInterval;
//0~1
@property(nonatomic, assign) CGFloat maxAlpha;
@property(nonatomic, assign) CGFloat minAlpha;
//0~1
@property(nonatomic, assign) CGFloat maxScale;
@property(nonatomic, assign) CGFloat minScale;
@property(nonatomic, assign) NSInteger count;
@property(nonatomic, assign) CGFloat maxRadius;
@property(nonatomic, assign) BOOL isAnimation;
-(void)startAnimation;
-(void)stopAnimation;
@end
#import "PulsatorLayer.h"
static NSString *kPulseAnimationKey = @"PulseAnimationKey";
@interface PulsatorLayer ()
@property (nonatomic, strong) CAShapeLayer *pulseLayer;
@end
@implementation PulsatorLayer
- (instancetype)init {
self = [super init];
if (self) {
self.animationDuration = 5;
self.animationInterval = 1;
self.maxAlpha = 0.7;
self.minAlpha = 0.1;
self.maxScale = 1.0;
self.minScale = 0.3;
self.count = 5;
self.maxRadius = 50;
self.instanceCount = _count;
self.instanceDelay = (self.animationDuration+self.animationInterval) / (CGFloat)_count;
self.repeatCount = MAXFLOAT;
[self addSublayer:self.pulseLayer];
}
return self;
}
- (CAShapeLayer *)pulseLayer {
if (!_pulseLayer) {
CAShapeLayer *pulseLayer = [CAShapeLayer layer];
pulseLayer.backgroundColor = self.outColor;
pulseLayer.contentsScale = [UIScreen mainScreen].scale;
pulseLayer.cornerRadius = self.maxRadius;
pulseLayer.bounds = CGRectMake(0, 0, self.maxRadius*2, self.maxRadius*2);
pulseLayer.opacity = 0.0;
_pulseLayer = pulseLayer;
}
return _pulseLayer;
}
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
}
-(void)setMaxRadius:(CGFloat)maxRadius {
_maxRadius = maxRadius;
if (_pulseLayer) {
CGRect bounds = _pulseLayer.bounds;
bounds.size.width = maxRadius*2;
bounds.origin.x = self.frame.origin.x;
bounds.origin.y = self.frame.origin.y;
bounds.size.height = maxRadius*2;
_pulseLayer.bounds = bounds;
_pulseLayer.cornerRadius = maxRadius;
}
}
//开始动画
-(void)startAnimation {
if (self.isAnimation) {
return;
}
//透明度
CABasicAnimation *opacityAnima = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityAnima.duration = self.animationDuration;
opacityAnima.fromValue = @(self.maxAlpha);
opacityAnima.toValue = @(self.minAlpha);
opacityAnima.removedOnCompletion = NO;
opacityAnima.cumulative = YES;
//脉冲源大小(layer*0.3)
CABasicAnimation *scaleAnima = [CABasicAnimation animationWithKeyPath:@"transform"];
scaleAnima.duration = self.animationDuration;
scaleAnima.fromValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, self.minScale, self.minScale, 0.0)];
scaleAnima.toValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, self.maxScale, self.maxScale, 0.0)];
scaleAnima.removedOnCompletion = NO;
scaleAnima.cumulative = YES;
//颜色
CABasicAnimation *colorAnima = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
colorAnima.duration = self.animationDuration;
colorAnima.fromValue = (__bridge id _Nullable)(self.inColor);
colorAnima.toValue = (__bridge id _Nullable)(self.outColor);
colorAnima.removedOnCompletion = NO;
colorAnima.cumulative = YES;
CAAnimationGroup *groupAnima = [CAAnimationGroup animation];
groupAnima.animations = @[opacityAnima, scaleAnima, colorAnima];
groupAnima.duration = self.animationDuration+self.animationInterval;
groupAnima.autoreverses = NO;//动画回退
groupAnima.removedOnCompletion = NO;
groupAnima.repeatCount = MAXFLOAT;
self.isAnimation = YES;
[self.pulseLayer addAnimation:groupAnima forKey:kPulseAnimationKey];
}
-(void)stopAnimation {
self.isAnimation = NO;
[self removeAnimationForKey:kPulseAnimationKey];
}
@end
网友评论