美文网首页
iOS开发 ---封装一个加载动画类

iOS开发 ---封装一个加载动画类

作者: 我是卖报的小行家 | 来源:发表于2022-05-30 11:55 被阅读0次

    (需要结合MBProgressHUD一起使用)新建一个类

    +(instancetype)showLoading; //显示
    +(void)showLoadingText:(NSString *)text delay:(NSInteger)delay;
    +(void)hideLoading;  //隐藏
    +(void)toast:(NSString *)text;
    
    #import "ZKLoadingView.h"
    #import "MBProgressHUD.h"
    //球宽高
    static CGFloat BallWidth = 12.0f;
    //球速
    static CGFloat BallSpeed = 0.7f;
    //球缩放比例
    static CGFloat BallZoomScale = 0.25;
    //暂停时间
    static CGFloat PauseSecond = 0.18;
    
    
    typedef NS_ENUM(NSInteger,BallMoveDirection){
        BallMoveDirectionPositive = 1,
        BallMoveDirectionNegative = -1
    };
    
    
    @interface ZKLoadingView ()
    @property (nonatomic, strong) UIView * Bg;
    //球的容器
    @property (nonatomic, strong) UIView *ballContainer;
    //绿球
    @property (nonatomic, strong) UIView *greenBall;
    //红球
    @property (nonatomic, strong) UIView *redBall;
    //黑球
    @property (nonatomic, strong) UIView *blackBall;
    //移动方向
    @property (nonatomic, assign) BallMoveDirection ballMoveDirection;
    //刷新器
    @property (nonatomic, strong) CADisplayLink *displayLink;
    @property (nonatomic, assign) BOOL bRegister;
    //开始动画
    - (void)startAnimated;
    //停止动画
    - (void)stopAnimated;
    @end
    
    @implementation ZKLoadingView
    
    + (instancetype)showLoading
    {
        [self hideLoading];
        UIView *view = [UIApplication sharedApplication].windows[0];
        ZKLoadingView *loading = [[ZKLoadingView alloc]initWithFrame:view.bounds];
        [view addSubview:loading];
        [loading startAnimated];
        return loading;
    }
    
    
    + (void)hideLoading
    {
        UIView *view = [UIApplication sharedApplication].windows[0];
        NSEnumerator *subViewsEnum = [view.subviews reverseObjectEnumerator]; //逆向遍历
        for (UIView *subViews in subViewsEnum) {
            if ([subViews isKindOfClass:self]) {
                ZKLoadingView *loading = (ZKLoadingView *)subViews;
                [loading stopAnimated];
                if (loading.displayLink) {
                    [loading.displayLink invalidate];
                    loading.displayLink = nil;
                    loading.bRegister = NO;
                }
                [loading removeFromSuperview];
                return;
            }
        }
        
        
        
    }
    
    + (void)showLoadingText:(NSString *)text delay:(NSInteger)delay
    {
        MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].windows[0] animated:YES];
        hud.contentColor = [UIColor whiteColor];
        hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor;
        hud.bezelView.color = UIColor.systemPinkColor;
        hud.mode = MBProgressHUDModeText;
        hud.label.text = text;
        hud.label.numberOfLines = 0;
        [hud hideAnimated:YES afterDelay:delay];
    }
    
    + (void)toast:(NSString *)text
    {
        [ZKLoadingView showLoadingText:text delay:1];
    }
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            [self createUI];
        }
        return self;
    }
    
    -(void)createUI{
       
        self.Bg = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 88, 88)];
        self.Bg.backgroundColor = UIColor.systemGrayColor;
        self.Bg.center = [self center];
        self.Bg.layer.cornerRadius = 8;
        self.Bg.layer.masksToBounds = YES;
        [self addSubview:self.Bg];
        
        self.ballContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 2.1*BallWidth, 2*BallWidth)];
        self.ballContainer.center = [self center];
        [self addSubview:self.ballContainer];
        
        self.greenBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, BallWidth, BallWidth)];
        self.greenBall.center = CGPointMake(BallWidth/2.0f, self.ballContainer.bounds.size.height/2.0f);
        self.greenBall.layer.cornerRadius = BallWidth/2.0f;
        self.greenBall.layer.masksToBounds = true;
        self.greenBall.backgroundColor = [UIColor colorWithRed:35/255.0f green:246/255.0f blue:235/255.0f alpha:1];
        [self.ballContainer addSubview:self.greenBall];
        
        self.redBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, BallWidth, BallWidth)];
        self.redBall.center = CGPointMake(self.ballContainer.bounds.size.width - BallWidth/2.0f, self.ballContainer.bounds.size.height/2.0f);
        self.redBall.layer.cornerRadius = BallWidth/2.0f;
        self.redBall.layer.masksToBounds = true;
        self.redBall.backgroundColor = [UIColor colorWithRed:255/255.0f green:46/255.0f blue:86/255.0f alpha:1];
        [self.ballContainer addSubview:self.redBall];
        
        //第一次动画是正向,绿球在上,红球在下,阴影会显示在绿球上
        self.blackBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, BallWidth, BallWidth)];
        self.blackBall.backgroundColor = [UIColor colorWithRed:12/255.0f green:11/255.0f blue:17/255.0f alpha:1];
        self.blackBall.layer.cornerRadius = BallWidth/2.0f;
        self.blackBall.layer.masksToBounds = true;
        [self.greenBall addSubview:self.blackBall];
        
        //初始化方向是正向
        self.ballMoveDirection = BallMoveDirectionPositive;
        self.bRegister = NO;
        //初始化刷新方法
        self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateBallAnimations)];
    }
    
    
    - (void)startAnimated
    {
        if (!self.bRegister) {
            [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
            self.bRegister = YES;
        }
    }
    
    - (void)stopAnimated
    {
        if (self.bRegister) {
            [self.displayLink removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
            self.bRegister = NO;
        }
    }
    
    - (void)pauseAnimated {
        [self stopAnimated];
        dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(PauseSecond*NSEC_PER_SEC));
        dispatch_after(delayTime, dispatch_get_main_queue(), ^{
            [self startAnimated];
        });
    }
    
    
    - (void)updateBallAnimations {
        if (self.ballMoveDirection == BallMoveDirectionPositive) {//正向运动
            //更新绿球位置
            CGPoint center = self.greenBall.center;
            center.x += BallSpeed;
            self.greenBall.center = center;
            
            //更新红球位置
            center = self.redBall.center;
            center.x -= BallSpeed;
            self.redBall.center = center;
            
            //缩放动画,绿球放大 红球变小
            self.greenBall.transform = [self ballLargerTransformOfCenterX:center.x];
            self.redBall.transform = [self ballSmallerTransformOfCenterX:center.x];
            
            //更新黑球位置
            CGRect blackBallFrame = [self.redBall convertRect:self.redBall.bounds toCoordinateSpace:self.greenBall];
            self.blackBall.frame = blackBallFrame;
            self.blackBall.layer.cornerRadius = self.blackBall.bounds.size.width/2.0f;
            
            //更新方向+改变三个球的相对位置
            if (CGRectGetMaxX(self.greenBall.frame) >= self.ballContainer.bounds.size.width || CGRectGetMinX(self.redBall.frame) <= 0) {
                //切换为反向
                self.ballMoveDirection = BallMoveDirectionNegative;
                //反向运动时,红球在上,绿球在下
                [self.ballContainer bringSubviewToFront:self.redBall];
                //黑球放在红球上面
                [self.redBall addSubview:self.blackBall];
                //暂停一下
                [self pauseAnimated];
            }
        }else if (self.ballMoveDirection == BallMoveDirectionNegative) {//反向运动
            //更新绿球位置
            CGPoint center = self.greenBall.center;
            center.x -= BallSpeed;
            self.greenBall.center = center;
            
            //更新红球位置
            center = self.redBall.center;
            center.x += BallSpeed;
            self.redBall.center = center;
            
            //缩放动画,红球放大 绿/黑球变小
            self.redBall.transform = [self ballLargerTransformOfCenterX:center.x];
            self.greenBall.transform = [self ballSmallerTransformOfCenterX:center.x];
            
            //更新黑球位置
            CGRect blackBallFrame = [self.greenBall convertRect:self.greenBall.bounds toCoordinateSpace:self.redBall];
            self.blackBall.frame = blackBallFrame;
            self.blackBall.layer.cornerRadius = self.blackBall.bounds.size.width/2.0f;
            
            //更新方向+改变三个球的相对位置
            if (CGRectGetMinX(self.greenBall.frame) <= 0 || CGRectGetMaxX(self.redBall.frame) >= self.ballContainer.bounds.size.width) {
                //切换为正向
                self.ballMoveDirection = BallMoveDirectionPositive;
                //正向运动时,绿球在上,红球在下
                [self.ballContainer bringSubviewToFront:self.greenBall];
                //黑球放在绿球上面
                [self.greenBall addSubview:self.blackBall];
                //暂停动画
                [self pauseAnimated];
            }
        }
    }
    
    
    //放大动画
    - (CGAffineTransform)ballLargerTransformOfCenterX:(CGFloat)centerX {
        CGFloat cosValue = [self cosValueOfCenterX:centerX];
        return CGAffineTransformMakeScale(1 + cosValue*BallZoomScale, 1 + cosValue*BallZoomScale);
    }
    
    //缩小动画
    - (CGAffineTransform)ballSmallerTransformOfCenterX:(CGFloat)centerX {
        CGFloat cosValue = [self cosValueOfCenterX:centerX];
        return CGAffineTransformMakeScale(1 - cosValue*BallZoomScale, 1 - cosValue*BallZoomScale);
    }
    
    //根据余弦函数获取变化区间 变化范围是0~1~0
    - (CGFloat)cosValueOfCenterX:(CGFloat)centerX {
        CGFloat apart = centerX - self.ballContainer.bounds.size.width/2.0f;
        //最大距离(球心距离Container中心距离)
        CGFloat maxAppart = (self.ballContainer.bounds.size.width - BallWidth)/2.0f;
        //移动距离和最大距离的比例
        CGFloat angle = apart/maxAppart*M_PI_2;
        //获取比例对应余弦曲线的Y值
        return cos(angle);
    }
    
    @end
    
    

    相关文章

      网友评论

          本文标题:iOS开发 ---封装一个加载动画类

          本文链接:https://www.haomeiwen.com/subject/ipdoprtx.html