CAAnimation--CALayer

来源:互联网 发布:淘宝热卖棉服 编辑:程序博客网 时间:2024/05/18 20:52

CircleView

#import <UIKit/UIKit.h>


typedef void(^ScaleCompletionHandler)();


@interface CircleView : UIView


- (instancetype) initWithFrame:(CGRect)frame andTheMaxSize:(CGFloat)maxSize theMinSize:(CGFloat)minSize theColor:(UIColor *)color;


- (void) startHeartBeat;

- (void) stopHeartBeat;


@end


#import "CircleView.h"


#pragma mark - CircleLayer class


@interface CircleLayer : CAShapeLayer


- (instancetype)initWithSuperViewFrame:(CGRect)superLayerFrame theMaxSize:(CGFloat)maxSize theMinSize:(CGFloat)minSize andTheColor:(UIColor *)color;


- (void) startAnimation;


- (void) stopAnimation;


@end


@interface CircleLayer ()


@property (nonatomic,assign) CGFloat maxSize;

@property (nonatomic,assign) CGFloat minSize;


@end


@implementation CircleLayer


- (instancetype)initWithSuperViewFrame:(CGRect)superLayerFrame theMaxSize:(CGFloat)maxSize theMinSize:(CGFloat)minSize andTheColor:(UIColor *)color {

    self = [superinit];

    if (self) {

        

        self.maxSize = maxSize;

        self.minSize = minSize;

        

        self.frame =CGRectMake(superLayerFrame.size.width/2 - maxSize/2, superLayerFrame.size.height/2 - maxSize/2, maxSize, maxSize);

        UIBezierPath *circlePath = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, maxSize, maxSize)];

        self.path = circlePath.CGPath;

        self.fillColor = color.CGColor;

        self.lineWidth =0;

        

    }

    return self;

}


#pragma mark Public methods


- (void)startAnimation {

    [selfperformScaleAnimation];

}


- (void)stopAnimation {

    [selfremoveAllAnimations];

}


#pragma mark Private methods


- (void) performScaleAnimation {

    CAKeyframeAnimation *animation = [CAKeyframeAnimationanimationWithKeyPath:@"transform.scale"];

    animation.keyTimes = @[@0, @0.5, @1];

    animation.values =@[@(self.maxSize /self.maxSize),@(self.minSize /self.maxSize),@(self.maxSize /self.maxSize)];

    animation.timingFunctions =@[[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionDefault], [CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionLinear]];

    animation.repeatCount = HUGE;

    animation.duration = 1.0;

    [self addAnimation:animationforKey:animation.keyPath];

}


@end



#pragma mark - WireLayer class


@interface WireLayer : CAShapeLayer


- (instancetype) initWithSuperLayerFrame:(CGRect)superLayerFrame

                              theMaxSize:(CGFloat)maxSize

                              theMinSize:(CGFloat)minSize theStartAngle:(CGFloat)startAngle theEndAngle:(CGFloat)endAngle

                             andTheColor:(UIColor *)color;


- (void) startAnimationWithStartAngle:(CGFloat)startAngle andEndAngle:(CGFloat)endAngle;


- (void) stopAnimation;


@end


@interface WireLayer ()


@property (nonatomic,assign) CGFloat maxSize;

@property (nonatomic,assign) CGFloat minSize;


@end


@implementation WireLayer


#pragma mark Override


- (instancetype)initWithSuperLayerFrame:(CGRect)superLayerFrame

                             theMaxSize:(CGFloat)maxSize

                             theMinSize:(CGFloat)minSize theStartAngle:(CGFloat)startAngle theEndAngle:(CGFloat)endAngle

                            andTheColor:(UIColor *)color {

    self = [superinit];

    if (self) {

        

        self.maxSize = maxSize *1.6;

        self.minSize = minSize *2.3;

        

        self.frame =CGRectMake(superLayerFrame.size.width/2 -self.maxSize/2, superLayerFrame.size.height/2 -self.maxSize/2,self.maxSize,self.maxSize);

        UIBezierPath *wire = [UIBezierPathbezierPathWithArcCenter:CGPointMake(self.bounds.size.width/2,self.bounds.size.height/2)radius:self.maxSize /2 startAngle:startAngleendAngle:endAngle clockwise:YES];

        self.path = wire.CGPath;

        self.fillColor =nil;

        self.strokeColor = color.CGColor;

        self.lineWidth =2.5;

        self.backgroundColor = [UIColorclearColor].CGColor;

        

    }

    return self;

}


#pragma mark Public methods


- (void)startAnimationWithStartAngle:(CGFloat)startAngle andEndAngle:(CGFloat)endAngle {

    [selfperformScaleAndRotationAnimationWithStartAngle:startAngleEndAngle:endAngle];

}


- (void)stopAnimation {

    [selfremoveAllAnimations];

}


#pragma mark Private methods


- (void) performScaleAndRotationAnimationWithStartAngle:(CGFloat)startAngle EndAngle:(CGFloat)endAngle {

    CAKeyframeAnimation *scaleAnimation = [CAKeyframeAnimationanimationWithKeyPath:@"transform.scale"];

    scaleAnimation.keyTimes = @[@0, @0.5, @1];

    scaleAnimation.values = @[@(self.maxSize /self.maxSize),@(self.minSize /self.maxSize),@(self.maxSize /self.maxSize)];

    scaleAnimation.timingFunctions =@[[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionDefault], [CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionDefault]];

    

    CAKeyframeAnimation *rotationAnimation = [CAKeyframeAnimationanimationWithKeyPath:@"transform.rotation.z"];

    rotationAnimation.keyTimes = @[@0, @0.5, @1];

    rotationAnimation.values = @[@(startAngle), @(endAngle), @(startAngle + 2*M_PI)];

    rotationAnimation.timingFunctions =@[[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionDefault], [CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionDefault]];

    

    CAAnimationGroup *group = [CAAnimationGroupanimation];

    group.animations = @[rotationAnimation, scaleAnimation];

    group.duration = 1.0;

    group.repeatCount = HUGE;

    

    [selfaddAnimation:group forKey:@"group"];

    

}


@end



#pragma mark - CircleView @implementation


@interface CircleView ()


@property (nonatomic,strong) CircleLayer *circleLayer;

@property (nonatomic,strong) WireLayer *topWireLayer;

@property (nonatomic,strong) WireLayer *bottomWireLayer;


@end


@implementation CircleView


#pragma mark Override


- (instancetype)initWithFrame:(CGRect)frame andTheMaxSize:(CGFloat)maxSize theMinSize:(CGFloat)minSize theColor:(UIColor *)color {

    self = [superinitWithFrame:frame];

    if (self) {

        

        self.circleLayer = [[CircleLayeralloc] initWithSuperViewFrame:self.boundstheMaxSize:maxSize theMinSize:minSizeandTheColor:color];

        [self.layeraddSublayer:self.circleLayer];


        self.topWireLayer = [[WireLayeralloc] initWithSuperLayerFrame:self.boundstheMaxSize:maxSize theMinSize:minSizetheStartAngle:(M_PI +M_PI_4) theEndAngle:(2*M_PI -M_PI_4) andTheColor:color];

        [self.layeraddSublayer:self.topWireLayer];

        

        self.bottomWireLayer = [[WireLayeralloc] initWithSuperLayerFrame:self.boundstheMaxSize:maxSize theMinSize:minSizetheStartAngle:(M_PI_4)theEndAngle:(M_PI_2 +M_PI_4) andTheColor:color];

        [self.layeraddSublayer:self.bottomWireLayer];

        

    }

    return self;

}


#pragma mark Public methods


- (void)startHeartBeat {

    [self.circleLayerstartAnimation];

    [self.topWireLayerstartAnimationWithStartAngle:(0)andEndAngle:(M_PI)];

    [self.bottomWireLayerstartAnimationWithStartAngle:(0)andEndAngle:(M_PI)];                        // 以自己的角度坐标为标准

}


- (void)stopHeartBeat {

    [self.circleLayerstopAnimation];

    [self.topWireLayerstopAnimation];

    [self.bottomWireLayerstopAnimation];

}


@end


GrilleView

#import <UIKit/UIKit.h>


@interface GrilleView : UIView


- (instancetype) initWithFrame:(CGRect)frame theMaxSize:(CGFloat)maxSize theMinSize:(CGFloat)minSize andTheGrilleColor:(UIColor *)color;


- (void) startWave;


- (void) stopWave;


@end

#import "GrilleView.h"

#import "Utils.h"


#pragma mark - GrilleLayer class


@interface GrilleLayer : CAShapeLayer


- (instancetype) initWithFrame:(CGRect)frame maxSize:(CGFloat)maxSize minSize:(CGFloat)minSize andTheColor:(UIColor *)color;


- (void) makeExpansion;


- (void) stopExpansion;


@end


@interface GrilleLayer ()


@property (nonatomic,assign) CGFloat maxSize;

@property (nonatomic,assign) CGFloat minSize;


@end


@implementation GrilleLayer


#pragma mark Override


- (instancetype)initWithFrame:(CGRect)frame maxSize:(CGFloat)maxSize minSize:(CGFloat)minSize andTheColor:(UIColor *)color {

    self = [superinit];

    if (self) {

        

        self.maxSize = maxSize;

        self.minSize = minSize;

        

        self.frame = frame;

        self.backgroundColor = [UIColorclearColor].CGColor;

        UIBezierPath *path = [UIBezierPathbezierPath];

        [path moveToPoint:CGPointMake(frame.size.width/2, frame.size.height - (frame.size.height/2 - minSize/2))];

        [path addLineToPoint:CGPointMake(frame.size.width/2, frame.size.height/2 - minSize/2)];

        self.path = path.CGPath;

        self.strokeColor = color.CGColor;

        self.lineWidth =6.0;

        self.lineCap =kCALineCapSquare;

        

    }

    return self;

}


#pragma mark Public method


- (void)makeExpansion {

    CAKeyframeAnimation *expansionAnimation = [CAKeyframeAnimationanimationWithKeyPath:@"transform.scale.y"];

    expansionAnimation.timingFunctions =@[[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionDefault], [CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionDefault]];

    expansionAnimation.keyTimes = @[@0, @0.45, @0.9];

    expansionAnimation.values = @[@(self.minSize /self.minSize),@(self.maxSize /self.minSize),@(self.minSize /self.minSize)];

    expansionAnimation.duration = 0.9;

    expansionAnimation.repeatCount = HUGE;

    [self addAnimation:expansionAnimationforKey:expansionAnimation.keyPath];

}


- (void)stopExpansion {

    [selfremoveAllAnimations];

}


@end


#pragma mark -GrilleView @implementation


@interface GrilleView ()


@property (nonatomic,copy) NSArray *grilles;

@property (nonatomic,assign) NSTimeInterval timeInterval;


@end


@implementation GrilleView


#pragma mark Override


- (instancetype)initWithFrame:(CGRect)frame theMaxSize:(CGFloat)maxSize theMinSize:(CGFloat)minSize andTheGrilleColor:(UIColor *)color {

    self = [superinitWithFrame:frame];

    if (self) {

        

        self.timeInterval =0.0f;

        CGFloat margin = 6.0f;

        

        GrilleLayer *grille_mid = [[GrilleLayeralloc] initWithFrame:CGRectMake(self.frame.size.width/2 - margin/2, self.frame.size.height/2 - maxSize/2, margin, maxSize) maxSize:maxSize minSize:minSize andTheColor:color];

        GrilleLayer *grille_left_one = [[GrilleLayeralloc] initWithFrame:CGRectMake(grille_mid.frame.origin.x - 4*margin, grille_mid.frame.origin.y, margin, maxSize)maxSize:maxSize minSize:minSizeandTheColor:color];

        GrilleLayer *grille_left_two = [[GrilleLayeralloc] initWithFrame:CGRectMake(grille_mid.frame.origin.x - 2*margin, grille_mid.frame.origin.y, margin, maxSize)maxSize:maxSize minSize:minSizeandTheColor:color];

        GrilleLayer *grille_right_two = [[GrilleLayeralloc] initWithFrame:CGRectMake(grille_mid.frame.origin.x + 2*margin, grille_mid.frame.origin.y, margin, maxSize)maxSize:maxSize minSize:minSizeandTheColor:color];

        GrilleLayer *grille_right_one = [[GrilleLayeralloc] initWithFrame:CGRectMake(grille_mid.frame.origin.x + 4*margin, grille_mid.frame.origin.y, margin, maxSize)maxSize:maxSize minSize:minSizeandTheColor:color];

        

        self.grilles =@[grille_left_one, grille_left_two, grille_mid, grille_right_two, grille_right_one];

        [self.grillesenumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx,BOOL * _Nonnull stop) {

            [self.layeraddSublayer:(GrilleLayer *)obj];

        }];

        

    }

    return self;

}


#pragma mark Public methods


- (void)startWave {

    [self.grillesenumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx,BOOL * _Nonnull stop) {

        GrilleLayer *grille = (GrilleLayer *)obj;

        delay(self.timeInterval, ^{

            [grille makeExpansion];

        });

        self.timeInterval +=0.15;

    }];

}


- (void)stopWave {

    [self.grillesenumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx,BOOL * _Nonnull stop) {

        GrilleLayer *grille = (GrilleLayer *)obj;

        [grille stopExpansion];

    }];

}


@end




0 0