iOS-旋转动画

作者: linbj | 来源:发表于2017-04-05 14:16 被阅读240次
    0DAAA493-70D7-4859-AEA6-3A6DE5A052EB1.gif

    看到一个有趣的选择效果图

    XLBallLoading

    用UIBezierPath和CAKeyframeAnimation实现这个效果。

    CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)
    两个参数,代表x和y方向缩放倍数。
    
    _ball2.transform = CGAffineTransformIdentity;
    在操作结束之后可对设置量进行还原
    
    - (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise
    可以画出一段弧线。
    看下各个参数的意义:
    center:圆心的坐标
    radius:半径
    startAngle:起始的弧度
    endAngle:圆弧结束的弧度
    clockwise:YES为顺时针,No为逆时针
    
    start和end angle的参数

    核心代码

    以左球为例。
        // 动画分为三个部分
        // 1.旋转到中球右边
        // 2.旋转到中球左边
        // 3.回到原位
        //-------第一个球的动画
        CGFloat width = _ballContainer.bounds.size.width;
        //小圆半径
        CGFloat r = (_ball1.bounds.size.width)*ballScale/2.0f;
        //大圆半径
        CGFloat R = (width/2 + r)/2.0;
        
        //1
        UIBezierPath *path1 = [UIBezierPath bezierPath];
        [path1 moveToPoint:_ball1.center];
        //画大圆
        [path1 addArcWithCenter:CGPointMake(R + r, width/2) radius:R startAngle:M_PI endAngle:M_PI*2 clockwise:NO];
        
        //2
        //画小圆
        UIBezierPath *path1_1 = [UIBezierPath bezierPath];
        [path1_1 addArcWithCenter:CGPointMake(width/2, width/2) radius:r*2 startAngle:M_PI*2 endAngle:M_PI clockwise:NO];
        [path1 appendPath:path1_1];
        
        //3
        //回到原处
        [path1 addLineToPoint:_ball1.center];
    

    完成旋转动画

    源代码

    //
    //  XLBallLoading.h
    //  XLBallLoadingDemo
    //
    //  Created by MengXianLiang on 2017/3/21.
    //  Copyright © 2017年 MengXianLiang. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface XLBallLoading : UIView
    
    -(void)start;
    -(void)stop;
    
    +(void)showInView:(UIView*)view;
    
    +(void)hideInView:(UIView*)view;
    
    @end
    
    
    //
    //  XLBallLoading.m
    //  XLBallLoadingDemo
    //
    //  Created by MengXianLiang on 2017/3/21.
    //  Copyright © 2017年 MengXianLiang. All rights reserved.
    //
    
    #import "XLBallLoading.h"
    
    static CGFloat ballScale = 1.5f;
    
    @interface XLBallLoading ()<CAAnimationDelegate>
    {
        
        UIVisualEffectView *_ballContainer;
        UIView *_ball1;
        UIView *_ball2;
        UIView *_ball3;
        
        BOOL _stopAnimationByUser;
    }
    @end
    
    @implementation XLBallLoading
    
    -(instancetype)initWithFrame:(CGRect)frame{
        if (self = [super initWithFrame:frame]) {
            [self initUI];
        }
        return self;
    }
    
    
    /**
     初始化ui
     */
    -(void)initUI{
        
        _ballContainer = [[UIVisualEffectView alloc]initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
        _ballContainer.frame = CGRectMake(0, 0, 100, 100);
        _ballContainer.center = CGPointMake(self.bounds.size.width/2.0f, self.bounds.size.height/2.0f);
        _ballContainer.layer.cornerRadius = 10.0f;
        _ballContainer.layer.masksToBounds = true;
        [self addSubview:_ballContainer];
        
        CGFloat ballWidth = 13.0f;
        
        //左球
        _ball1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, ballWidth, ballWidth)];
        _ball1.center = CGPointMake(ballWidth/2.0f, _ballContainer.bounds.size.height/2.0f);
        _ball1.layer.cornerRadius = ballWidth/2.0f;
        _ball1.backgroundColor = [UIColor colorWithRed:54/255.0 green:136/255.0 blue:250/255.0 alpha:1];
        [_ballContainer addSubview:_ball1];
        //中球
        _ball2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, ballWidth, ballWidth)];
        _ball2.center = CGPointMake(_ballContainer.bounds.size.width/2.0f, _ballContainer.bounds.size.height/2.0f);
        _ball2.layer.cornerRadius = ballWidth/2.0f;
        _ball2.backgroundColor = [UIColor colorWithRed:100/255.0 green:100/255.0 blue:100/255.0 alpha:1];
        [_ballContainer addSubview:_ball2];
        
        //右球
        _ball3 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, ballWidth, ballWidth)];
        _ball3.center = CGPointMake(_ballContainer.bounds.size.width - ballWidth/2.0f, _ballContainer.bounds.size.height/2.0f);
        _ball3.layer.cornerRadius = ballWidth/2.0f;
        _ball3.backgroundColor = [UIColor colorWithRed:234/255.0 green:67/255.0 blue:69/255.0 alpha:1];
        _ball3.hidden = YES;
        [_ballContainer addSubview:_ball3];
    }
    
    -(void)startPathAnimate{
        
        
        // 动画分为三个部分
        // 1.旋转到中球右边
        // 2.旋转到中球左边
        // 3.回到原位
        //-------第一个球的动画
        CGFloat width = _ballContainer.bounds.size.width;
        //小圆半径
        CGFloat r = (_ball1.bounds.size.width)*ballScale/2.0f;
        //大圆半径
        CGFloat R = (width/2 + r)/2.0;
        
        //1
        UIBezierPath *path1 = [UIBezierPath bezierPath];
        [path1 moveToPoint:_ball1.center];
        //画大圆
        [path1 addArcWithCenter:CGPointMake(R + r, width/2) radius:R startAngle:M_PI endAngle:M_PI*2 clockwise:NO];
        
        //2
        //画小圆
        UIBezierPath *path1_1 = [UIBezierPath bezierPath];
        [path1_1 addArcWithCenter:CGPointMake(width/2, width/2) radius:r*2 startAngle:M_PI*2 endAngle:M_PI clockwise:NO];
        [path1 appendPath:path1_1];
        
        //3
        //回到原处
        [path1 addLineToPoint:_ball1.center];
        
        
        //执行动画
        CAKeyframeAnimation *animation1 = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        animation1.path = path1.CGPath;
        animation1.removedOnCompletion = YES;
        animation1.duration = [self animationDuration];
        animation1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        [_ball1.layer addAnimation:animation1 forKey:@"animation1"];
        
        
        //-------第三个球的动画
        UIBezierPath *path3 = [UIBezierPath bezierPath];
        [path3 moveToPoint:_ball3.center];
        //画大圆
        [path3 addArcWithCenter:CGPointMake(width - (R + r), width/2) radius:R startAngle:2*M_PI endAngle:M_PI clockwise:NO];
        //画小圆
        UIBezierPath *path3_1 = [UIBezierPath bezierPath];
        [path3_1 addArcWithCenter:CGPointMake(width/2, width/2) radius:r*2 startAngle:M_PI endAngle:M_PI*2 clockwise:NO];
        [path3 appendPath:path3_1];
        //回到原处
        [path3 addLineToPoint:_ball3.center];
        //执行动画
        CAKeyframeAnimation *animation3 = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        animation3.path = path3.CGPath;
        animation3.removedOnCompletion = YES;
        animation3.duration = [self animationDuration];
        animation3.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        animation3.delegate = self;
        [_ball3.layer addAnimation:animation3 forKey:@"animation3"];
    }
    
    
    //放大缩小动画
    -(void)animationDidStart:(CAAnimation *)anim{
        
        CGFloat delay = 0.3f;
        CGFloat duration = [self animationDuration]/2 - delay;
        
        [UIView animateWithDuration:duration delay:delay options:UIViewAnimationOptionCurveEaseOut| UIViewAnimationOptionBeginFromCurrentState animations:^{
            //使ball变大
            _ball1.transform = CGAffineTransformMakeScale(ballScale, ballScale);
            _ball2.transform = CGAffineTransformMakeScale(ballScale, ballScale);
            _ball3.transform = CGAffineTransformMakeScale(ballScale, ballScale);
        } completion:^(BOOL finished) {
            [UIView animateWithDuration:duration delay:delay options:UIViewAnimationOptionCurveEaseInOut| UIViewAnimationOptionBeginFromCurrentState animations:^{
                //变回原形
                _ball1.transform = CGAffineTransformIdentity;
                _ball2.transform = CGAffineTransformIdentity;
                _ball3.transform = CGAffineTransformIdentity;
            } completion:nil];
        }];
    }
    
    -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
        if (_stopAnimationByUser) {return;}
        [self startPathAnimate];
    }
    
    
    -(CGFloat)animationDuration{
        return 1.6f;
    }
    
    #pragma mark -
    #pragma mark 显示隐藏方法
    -(void)start{
        [self startPathAnimate];
        _stopAnimationByUser = false;
    }
    
    -(void)stop{
        _stopAnimationByUser = true;
        [_ball1.layer removeAllAnimations];
        [_ball1 removeFromSuperview];
        [_ball2.layer removeAllAnimations];
        [_ball2 removeFromSuperview];
        [_ball3.layer removeAllAnimations];
        [_ball3 removeFromSuperview];
    }
    
    +(void)showInView:(UIView *)view{
        [self hideInView:view];
        XLBallLoading *loading = [[XLBallLoading alloc] initWithFrame:view.bounds];
        [view addSubview:loading];
        [loading start];
    }
    
    +(void)hideInView:(UIView *)view{
        for (XLBallLoading *loading in view.subviews) {
            if ([loading isKindOfClass:[XLBallLoading class]]) {
                [loading stop];
                [loading removeFromSuperview];
            }
        }
    }
    
    @end
    
    

    相关文章

      网友评论

        本文标题:iOS-旋转动画

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