IOS仿最新版爱奇异loading动画

爱奇异更新版本之后,那个loading效果比较简洁,却又不失美观,遂仿制一把,以供广大程序员交流学习,效果图如下,


效果图中是垂直效果,但只要在路径那里改一下即可,还有一个缩放动画未添加,留给看官们自己处理大笑大笑


动画分析:

圆弧动画:UIBezierPath +CAShapeLayer 

 其中UIBezierPath画出左右2边的圆弧,然后用基本动画的storkEnd或storkStart来驱动即可,达到动画效果

代码如下:


 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animation.duration = 0.7f;
    animation.fromValue = @(1);
    animation.toValue = @(0.0);
    //animation.delegate = self;
    //animation.repeatCount = MAXFLOAT;
    
    // 保持动画结束时的状态
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    [animation setValue:@"arcRotateAnim" forKey:@"animationName"];
    
    [self.leftArcLayer addAnimation:animation forKey:@""];
    [self.rightArcLayer addAnimation:animation forKey:@""];
    
    
    //画布旋转动画
    CABasicAnimation *BasicAnimation=[CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    
    BasicAnimation.toValue=@(M_PI*2);
    BasicAnimation.duration= 0.7;
    
    //BasicAnimation.delegate=self;
    [BasicAnimation setValue:@"BasicAnimationRotation" forKey:@"animationName"];
    [self.layer removeAllAnimations];
    [self.layer addAnimation:BasicAnimation forKey:@"BasicAnimationRotation"];



图层分析 :CAShapeLayer在强大之处这里不细说,本案例中主要有4个图层 ,分别使用懒加载实现,代码如下:



/**
 重写get属性

 @return CAShapeLayer
 */
-(CAShapeLayer*) leftArcLayer{


    if (!_leftArcLayer) {
        _leftArcLayer = [CAShapeLayer layer];
        CGPoint center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2);
        
        UIBezierPath *path = [UIBezierPath bezierPath];
        
        [path addArcWithCenter:center radius:25 startAngle: -PI / 2 endAngle:PI / 2 clockwise:YES];
        
        
        _leftArcLayer.borderColor = [UIColor blackColor].CGColor;
        _leftArcLayer.lineWidth = 1.f;
        _leftArcLayer.path = path.CGPath;
        _leftArcLayer.fillColor = [UIColor clearColor].CGColor;
        _leftArcLayer.strokeColor = [UIColor greenColor].CGColor;
    }
    return _leftArcLayer;
    
}


-(CAShapeLayer*) rightArcLayer{
    
    
    if (!_rightArcLayer) {
        _rightArcLayer = [CAShapeLayer layer];
        CGPoint center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2);
        
        UIBezierPath *path = [UIBezierPath bezierPath];
        
        [path addArcWithCenter:center radius:25 startAngle: PI / 2 endAngle:-PI / 2 clockwise:YES];
        
        
        _rightArcLayer.borderColor = [UIColor blackColor].CGColor;
        _rightArcLayer.lineWidth = 1.f;
        _rightArcLayer.path = path.CGPath;
        _rightArcLayer.fillColor = [UIColor clearColor].CGColor;
        _rightArcLayer.strokeColor = [UIColor greenColor].CGColor;
    }
    return _rightArcLayer;
    
}


-(CAShapeLayer*) leftPointLayer{

    if (!_leftPointLayer) {
        _leftPointLayer = [CAShapeLayer layer];
        CGPoint center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2);

        _leftPointLayer.bounds = CGRectMake(0, 0, 2, 2);
        _leftPointLayer.position = center;
        _leftPointLayer.backgroundColor = [UIColor greenColor].CGColor;
    }
    return _leftPointLayer;
}

-(CAShapeLayer*) rightPointLayer{
    
    if (!_rightPointLayer) {
        _rightPointLayer = [CAShapeLayer layer];
        CGPoint center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2);
        _rightPointLayer.bounds = CGRectMake(0, 0, 2, 2);
        _rightPointLayer.position = center;
        _rightPointLayer.backgroundColor = [UIColor greenColor].CGColor;
    }
    return _rightPointLayer;
}



圆点动画:基本动画中的位移动画:代码如下:

-(void) middlePointMoveAnim{

    CABasicAnimation *moveAnim = [CABasicAnimation animationWithKeyPath:@"position"];
    CGPoint center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2);
    moveAnim.fromValue = [NSValue valueWithCGPoint:center];
    moveAnim.toValue = [NSValue valueWithCGPoint:CGPointMake(center.x , center.y  - 25)];
    moveAnim.duration = 0.5f;
    moveAnim.delegate = self;
    
    moveAnim.fillMode = kCAFillModeForwards;
    moveAnim.removedOnCompletion = NO;
    
    moveAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
    //[self.leftPointLayer removeAllAnimations];
    [moveAnim setValue:@"positionAnimation" forKey:@"moveAnim"];
    [self.leftPointLayer addAnimation:moveAnim forKey:@""];
    
    
    
    CABasicAnimation *moveRightAnim = [CABasicAnimation animationWithKeyPath:@"position"];
   
    moveRightAnim.fromValue = [NSValue valueWithCGPoint:center];
    moveRightAnim.toValue = [NSValue valueWithCGPoint:CGPointMake(center.x , center.y  + 25)];
    moveRightAnim.duration = 0.5f;
    //moveRightAnim.delegate = self;
    moveRightAnim.fillMode = kCAFillModeForwards;
    moveRightAnim.removedOnCompletion = NO;
    moveRightAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    //[self.rightPointLayer removeAllAnimations];
    [self.rightPointLayer addAnimation:moveRightAnim forKey:@""];

}





全部代码如下:

.h文件


@interface ShapeLayer_BezierParh : UIView<CAAnimationDelegate>

@property(nonatomic,strong) CAShapeLayer* leftArcLayer;
@property(nonatomic,strong) CAShapeLayer* rightArcLayer;

@property(nonatomic,strong) CAShapeLayer* leftPointLayer;
@property(nonatomic,strong) CAShapeLayer* rightPointLayer;

-(void) startAnim;

-(void) middlePointMoveAnim;

@end

.m文件:

#import "ShapeLayer_BezierParh.h"

#define PI 3.1415926

@implementation ShapeLayer_BezierParh


-(instancetype) initWithFrame:(CGRect)frame{

    if (self = [super initWithFrame:frame]) {
        
        [self.layer addSublayer:self.leftArcLayer];
        [self.layer addSublayer:self.rightArcLayer];
        [self.layer addSublayer:self.leftPointLayer];
        [self.layer addSublayer:self.rightPointLayer];
    }
    
    return self;

}


/**
 重写get属性

 @return CAShapeLayer
 */
-(CAShapeLayer*) leftArcLayer{


    if (!_leftArcLayer) {
        _leftArcLayer = [CAShapeLayer layer];
        CGPoint center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2);
        
        UIBezierPath *path = [UIBezierPath bezierPath];
        
        [path addArcWithCenter:center radius:25 startAngle: -PI / 2 endAngle:PI / 2 clockwise:YES];
        
        
        _leftArcLayer.borderColor = [UIColor blackColor].CGColor;
        _leftArcLayer.lineWidth = 1.f;
        _leftArcLayer.path = path.CGPath;
        _leftArcLayer.fillColor = [UIColor clearColor].CGColor;
        _leftArcLayer.strokeColor = [UIColor greenColor].CGColor;
    }
    return _leftArcLayer;
    
}


-(CAShapeLayer*) rightArcLayer{
    
    
    if (!_rightArcLayer) {
        _rightArcLayer = [CAShapeLayer layer];
        CGPoint center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2);
        
        UIBezierPath *path = [UIBezierPath bezierPath];
        
        [path addArcWithCenter:center radius:25 startAngle: PI / 2 endAngle:-PI / 2 clockwise:YES];
        
        
        _rightArcLayer.borderColor = [UIColor blackColor].CGColor;
        _rightArcLayer.lineWidth = 1.f;
        _rightArcLayer.path = path.CGPath;
        _rightArcLayer.fillColor = [UIColor clearColor].CGColor;
        _rightArcLayer.strokeColor = [UIColor greenColor].CGColor;
    }
    return _rightArcLayer;
    
}


-(CAShapeLayer*) leftPointLayer{

    if (!_leftPointLayer) {
        _leftPointLayer = [CAShapeLayer layer];
        CGPoint center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2);

        _leftPointLayer.bounds = CGRectMake(0, 0, 2, 2);
        _leftPointLayer.position = center;
        _leftPointLayer.backgroundColor = [UIColor greenColor].CGColor;
    }
    return _leftPointLayer;
}

-(CAShapeLayer*) rightPointLayer{
    
    if (!_rightPointLayer) {
        _rightPointLayer = [CAShapeLayer layer];
        CGPoint center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2);
        _rightPointLayer.bounds = CGRectMake(0, 0, 2, 2);
        _rightPointLayer.position = center;
        _rightPointLayer.backgroundColor = [UIColor greenColor].CGColor;
    }
    return _rightPointLayer;
}


-(void) startAnim{
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animation.duration = 0.7f;
    animation.fromValue = @(1);
    animation.toValue = @(0.0);
    //animation.delegate = self;
    //animation.repeatCount = MAXFLOAT;
    
    // 保持动画结束时的状态
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    [animation setValue:@"arcRotateAnim" forKey:@"animationName"];
    
    [self.leftArcLayer addAnimation:animation forKey:@""];
    [self.rightArcLayer addAnimation:animation forKey:@""];
    
    
    //画布旋转动画
    CABasicAnimation *BasicAnimation=[CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    
    BasicAnimation.toValue=@(M_PI*2);
    BasicAnimation.duration= 0.7;
    
    //BasicAnimation.delegate=self;
    [BasicAnimation setValue:@"BasicAnimationRotation" forKey:@"animationName"];
    [self.layer removeAllAnimations];
    [self.layer addAnimation:BasicAnimation forKey:@"BasicAnimationRotation"];

    
    
    dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.8 * NSEC_PER_SEC));
    dispatch_after(delayTime, dispatch_get_main_queue(), ^{
        [self middlePointMoveAnim];
        
    });

}

-(void) middlePointMoveAnim{

    CABasicAnimation *moveAnim = [CABasicAnimation animationWithKeyPath:@"position"];
    CGPoint center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2);
    moveAnim.fromValue = [NSValue valueWithCGPoint:center];
    moveAnim.toValue = [NSValue valueWithCGPoint:CGPointMake(center.x , center.y  - 25)];
    moveAnim.duration = 0.5f;
    moveAnim.delegate = self;
    
    moveAnim.fillMode = kCAFillModeForwards;
    moveAnim.removedOnCompletion = NO;
    
    moveAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
    //[self.leftPointLayer removeAllAnimations];
    [moveAnim setValue:@"positionAnimation" forKey:@"moveAnim"];
    [self.leftPointLayer addAnimation:moveAnim forKey:@""];
    
    
    
    CABasicAnimation *moveRightAnim = [CABasicAnimation animationWithKeyPath:@"position"];
   
    moveRightAnim.fromValue = [NSValue valueWithCGPoint:center];
    moveRightAnim.toValue = [NSValue valueWithCGPoint:CGPointMake(center.x , center.y  + 25)];
    moveRightAnim.duration = 0.5f;
    //moveRightAnim.delegate = self;
    moveRightAnim.fillMode = kCAFillModeForwards;
    moveRightAnim.removedOnCompletion = NO;
    moveRightAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    //[self.rightPointLayer removeAllAnimations];
    [self.rightPointLayer addAnimation:moveRightAnim forKey:@""];

}

-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{

    if([[anim valueForKey:@"animationName"] isEqualToString:@"arcRotateAnim"]){
    
        NSLog(@"144----------------arcRotateAnim:stop  %d",flag);
       
        if(flag){
            dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC));
            dispatch_after(delayTime, dispatch_get_main_queue(), ^{
               [self middlePointMoveAnim];
                
            });
        }
        
        
        
        
    }
    else if([[anim valueForKey:@"moveAnim"] isEqualToString:@"positionAnimation"]){
    
        NSLog(@"171----------------moveAnim:stop  :%d",flag);
        
        if(flag){
            dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC));
            dispatch_after(delayTime, dispatch_get_main_queue(), ^{
                [self startAnim];
            });

        }
        
    }

}


@end



在vc中的测试代码如下:

-(void) testShapeLayer{

    
   self.bezierParhLayer = [[ShapeLayer_BezierParh alloc] initWithFrame:CGRectMake((CGRectGetWidth(self.view.frame) / 2) - 25, 100, 100, 100)];

    //self.bezierParhLayer.backgroundColor = [UIColor wh];
    
    [self.view addSubview:self.bezierParhLayer];
    
   
}

将开启动画放在一个按钮下,点击按钮进行动画启动:

[self.bezierParhLayer middlePointMoveAnim];



其中属性:

@property(nonatomic,strong) ShapeLayer_BezierParh* bezierParhLayer;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值