iOS动画

作者: happycheng | 来源:发表于2017-12-20 13:59 被阅读0次

    实现动画方法有很多种:图片动画最简单的是用数组放多张图片,用UIImageView展示,但耗内存。UIView动画(包含转场动画)。可以用layer,可以配合贝塞尔曲线,贝塞尔曲线是画图的,动画效果都是通过CAAnimation类的子类(CAAnimation是抽象类)来完成的。CAAnimation类的子类包括了CAAnimationGroup,CAPropertyAnimation,CATransition,而CAPropertyAniamtion(同为抽象类)也衍生了CABasicAnimation和CAKeyframeAnimation。用UIView的animation实现的动画本质上也是通过CALayer来实现的

    UIView动画 animateWithDuration方法

    //下划线位置变换
        [UIView animateWithDuration:0.25f animations:^{
            
            self.lineView.frame = CGRectMake(((screenWidth/self.titleArr.count)-40)/2+(screenWidth/self.titleArr.count)*index, 50-4, 40, 3);
        }];
    
    [self.myTableView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(self.view);
        }];
        
        //如果想要约束变换之后实现动画效果,则需要执行如下操作
        //layoutIfNeeded   告知页面布局立刻更新
        [UIView animateWithDuration:0.3 animations:^{
            [self.view layoutIfNeeded];   //更新界面
        }];
    
    //单视图动画
        [UIView transitionWithView:sender duration:2.0f options:UIViewAnimationOptionTransitionFlipFromRight animations:nil completion:^(BOOL finished) {
            [self.navigationController pushViewController:vc animated:YES];
        }];
    
    //双视图转场动画   transitionFromView
    - (void)onAnimationBtn:(UIButton *)sender {
        CFFAnimationViewController *vc = [CFFAnimationViewController new];
    //    [self.navigationController pushViewController:vc animated:YES];
        
        //双视图转场动画
        [UIView transitionFromView:self.view toView:vc.view duration:2.0f options:UIViewAnimationOptionTransitionFlipFromRight completion:nil];
    }
    

    UIView动画 beginAnimations commitAnimations

     // 从beginAnimations到commitAnimations完成一次完成的动画    layoutIfNeeded必须要的,不然动画执行无效
            [UIView beginAnimations:nil context:nil]; //开始动画
            [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
            [UIView setAnimationDuration:0.3f];  //动画时长
            
            [self.photoView mas_updateConstraints:^(MASConstraintMaker *make) {
                make.left.right.equalTo(self.view);
                make.bottom.equalTo(self.view.mas_bottom);
                make.height.mas_equalTo(@80);
            }];
            
            [self.bottomView mas_updateConstraints:^(MASConstraintMaker *make) {
                make.right.left.equalTo(self.view);
                make.bottom.equalTo(self.view).offset(-80);
                make.height.mas_equalTo(@50);
            }];
            self.bottomConstraint.constant = 50+80;
            [self.view layoutIfNeeded];
            [UIView commitAnimations];  //提交动画
    

    贝塞尔曲线

    //圆形循环
    - (void)dongHua {
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(60 / 2.f, 60 / 2.f)
                                                            radius:60 / 2.f
                                                        startAngle:0
                                                          endAngle:M_PI * 2
                                                         clockwise:YES];
        
        CAShapeLayer *shapelayer = [CAShapeLayer layer];
        shapelayer.frame = CGRectMake(100, 100, 60, 60);
        shapelayer.path = path.CGPath;
        shapelayer.lineWidth = 4.0f;
        shapelayer.lineCap = kCALineCapSquare;  //边缘线类型
        shapelayer.fillColor = [UIColor clearColor].CGColor;
        shapelayer.strokeColor = [UIColor orangeColor].CGColor;
        shapelayer.strokeStart = 0.0f;
        shapelayer.strokeEnd = 0.1f;
        [self.view.layer addSublayer:shapelayer];
        
        CABasicAnimation *basicAnmation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        basicAnmation.duration = 2.0;
        basicAnmation.repeatCount = 1;
        basicAnmation.fromValue = [NSNumber numberWithInt:0.0f];
        basicAnmation.toValue = [NSNumber numberWithInt:1.0f];
        basicAnmation.removedOnCompletion = NO;
        basicAnmation.fillMode = kCAFillModeForwards;
        [shapelayer addAnimation:basicAnmation forKey:nil];
    }
    

    核心动画

    /*
     CAAnimation是所有动画类的父类,但是它不能直接使用,应该使用它的子类。
     能用的动画类只有4个子类:CABasicAnimation、CAKeyframeAnimation、CATransition、CAAnimationGroup
     */
    - (void)animationLabelView {
        _animationLab = [[UILabel alloc] initWithFrame:CGRectMake(10, 40, 60, 30)];
        _animationLab.textAlignment = NSTextAlignmentCenter;
        _animationLab.text = @"动画";
        _animationLab.backgroundColor = [UIColor orangeColor];
        _animationLab.textColor = [UIColor whiteColor];
        [self.view addSubview:_animationLab];
        
        //闪烁动画
        //    [_animationLab.layer addAnimation:[self opacityForever_Animation:0.5f] forKey:nil];
        
        //纵向横向移动
        //    [_animationLab.layer addAnimation:[self movex:1.0f x:[NSNumber numberWithFloat:200.0f]] forKey:nil];
        
        //缩放
        //    [_animationLab.layer addAnimation:[self scale:[NSNumber numberWithFloat:1.0f] orgin:[NSNumber numberWithFloat:0.3f] durTimes:0.5f Rep:MAXFLOAT] forKey:nil];
        
        //组合
        //    NSArray *animationArray = [NSArray arrayWithObjects:[self opacityForever_Animation:0.5f],[self movex:1.0f x:[NSNumber numberWithFloat:200.0f]],[self scale:[NSNumber numberWithFloat:1.0f] orgin:[NSNumber numberWithFloat:0.3f] durTimes:0.5f Rep:MAXFLOAT], nil];
        //    [_animationLab.layer addAnimation:[self groupAnimation:animationArray durTimes:1.0f Rep:MAXFLOAT] forKey:nil];
        
        
        //路径
        //    CGMutablePathRef pathRef = CGPathCreateMutable();
        //    CGPathMoveToPoint(pathRef, nil, 30, 77);  //
        //    CGPathAddCurveToPoint(pathRef, nil, 50, 50, 60, 200, 200, 200);
        //    [_animationLab.layer addAnimation:[self keyframeAnimation:pathRef durTimes:1.0f Rep:MAXFLOAT] forKey:nil];
        
        
        //旋转
        //    [_animationLab.layer addAnimation:[self rotation:2 degree:kRadianToDegrees(180) direction:1 repeatCount:MAXFLOAT] forKey:nil];
        
        
        
        //绕y旋转
    //    [_animationLab.layer addAnimation:[self rotationFromYWithDur:1.0f] forKey:nil];
        //绕y旋转   方法一:旋转时过渡平滑
    //    [_animationLab.layer addAnimation:[self rotationFromYWithDur:1.0f] forKey:@"rotationAnimation"];
        //UIView动画
    //    方法二:如同方法一,但是过渡时效果没有方法一的舒服,感觉差那么一点
        //@param duration 持续时间
        //@param delay  延时时间
        //@param options  方式
        [UIView animateWithDuration:1.0
                              delay:0
                            options:UIViewAnimationOptionRepeat
                         animations:^{
                             //你想绕哪个轴哪个轴就为 1,其中的参数(角度, x, y, z)
                             _animationLab.layer.transform=CATransform3DMakeRotation(M_PI, 0, 1, 0);
                         }
                         completion:^(BOOL finished) {
                             //你想绕哪个轴哪个轴就为 1,其中的参数(角度, x, y, z)
                             _animationLab.layer.transform=CATransform3DMakeRotation(M_PI, 0, 1, 0);
                         }];
    }
    
    #pragma mark - 永久闪烁的动画
    - (CABasicAnimation *)opacityForever_Animation:(float)time {
        //透明度
        CABasicAnimation *baseAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; //必须是opacity(不透明度)
        
        baseAnimation.fromValue = [NSNumber numberWithFloat:1.0f];
        baseAnimation.toValue = [NSNumber numberWithFloat:0.0f];  //透明度
        baseAnimation.fillMode = kCAFillModeForwards;  //fillMode的作用就是决定当前对象过了非active时间段的行为. 比如动画开始之前,动画结束之后。如果是一个动画CAAnimation,则需要将其removedOnCompletion设置为NO,要不然fillMode不起作用.kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
        /*
         kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
        kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
        kCAFillModeBackwards 这个和kCAFillModeForwards是相对的,就是在动画开始前,你只要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始.你可以这样设定测试代码,将一个动画加入一个layer的时候延迟5秒执行.然后就会发现在动画没有开始的时候,只要动画被加入了layer,layer便处于动画初始状态
        kCAFillModeBoth 理解了上面两个,这个就很好理解了,这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态.
         */
        baseAnimation.autoreverses = YES;   //动画结束时是否进行逆反
        baseAnimation.duration = time;
        baseAnimation.repeatCount = MAXFLOAT;
        baseAnimation.removedOnCompletion = NO;    //YES就是动画完成后自动变回原样,动画完成后是否移除动画,.默认为YES.此属性为YES时, fillMode不可用
        baseAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];  //没有的话,是均匀的动画   timingFunction速度控制函数
        
        
        
        //缩放
    //    CABasicAnimation *baseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];  //transform.scale(变换 缩放)
    //    baseAnimation.fromValue = [NSNumber numberWithFloat:1.0f];
    //    baseAnimation.toValue = [NSNumber numberWithFloat:0.0f];  //缩放值
    //    baseAnimation.autoreverses = YES;     //动画结束时是否执行逆动画
    //    baseAnimation.duration = time;
    //    baseAnimation.repeatCount = MAXFLOAT;    //是否动画永远持续
    
        return baseAnimation;
    }
    
    #pragma mark - 纵向、横向移动
    - (CABasicAnimation *)movex:(float)time x:(NSNumber *)x {
        CABasicAnimation *baseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"]; //.y的话,就会向下移
        baseAnimation.toValue = x;
        baseAnimation.duration = time;
        baseAnimation.repeatCount = MAXFLOAT;
        baseAnimation.fillMode = kCAFillModeForwards;
        baseAnimation.removedOnCompletion = NO;  //为YES,就会又回到原位置,动画完成后是否移除动画,.默认为YES.此属性为YES时, fillMode不可用
        
        return baseAnimation;
    }
    
    #pragma mark - 缩放
    -(CABasicAnimation *)scale:(NSNumber *)Multiple orgin:(NSNumber *)orginMultiple durTimes:(float)time Rep:(float)repertTimes {
        CABasicAnimation *baseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        baseAnimation.fromValue = Multiple;
        baseAnimation.toValue = orginMultiple;
        baseAnimation.duration = time;   //不设置,会有个默认的缩放时间
        baseAnimation.repeatCount = repertTimes;
        baseAnimation.autoreverses = YES;
        baseAnimation.fillMode = kCAFillModeForwards;
        baseAnimation.removedOnCompletion = NO;
        
        return baseAnimation;
    }
    
    #pragma mark - 组合动画
    -(CAAnimationGroup *)groupAnimation:(NSArray *)animationArray durTimes:(float)time Rep:(float)repeatTimes {
        CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
        animationGroup.animations = animationArray;
        animationGroup.duration = time;
        animationGroup.repeatCount = repeatTimes;
        animationGroup.removedOnCompletion = NO;
        animationGroup.fillMode = kCAFillModeForwards;
        
        return animationGroup;
    }
    
    #pragma mark - 路径动画
    -(CAKeyframeAnimation *)keyframeAnimation:(CGMutablePathRef)path durTimes:(float)time Rep:(float)repeatTimes {
        CAKeyframeAnimation *keyFrameAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        keyFrameAnimation.path = path;
        keyFrameAnimation.duration = time;
        keyFrameAnimation.repeatCount = repeatTimes;
        keyFrameAnimation.autoreverses = YES;
        keyFrameAnimation.removedOnCompletion = NO;
        keyFrameAnimation.fillMode = kCAFillModeForwards;
        keyFrameAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];  //没有设置,就是匀速
        
        return keyFrameAnimation;
    }
    
    #pragma mark - 旋转
    -(CABasicAnimation *)rotation:(float)dur degree:(float)degree direction:(int)direction repeatCount:(int)repeatCount {
        CATransform3D transform3D = CATransform3DMakeRotation(degree, 0, 0, direction);
        CABasicAnimation *baseAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
        baseAnimation.toValue = [NSValue valueWithCATransform3D:transform3D];
        baseAnimation.duration = dur;
        baseAnimation.repeatCount = repeatCount;
        baseAnimation.autoreverses = NO;   //动画结束时是否进行逆动画
        baseAnimation.fillMode = kCAFillModeForwards;
        baseAnimation.cumulative = NO;  //指定动画是否为累加效果,默认为NO
    //    baseAnimation.delegate = self;
        
        return baseAnimation;
    }
    
    //沿y旋转
    //- (CABasicAnimation *)rotationFromYWithDur:(float)duration {
    //    CABasicAnimation *baseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
    //    baseAnimation.duration = duration;
    //    baseAnimation.repeatCount = HUGE_VALF;  //重复不停
    //    baseAnimation.fromValue = [NSNumber numberWithFloat:0];
    //    baseAnimation.toValue = [NSNumber numberWithFloat:M_PI*2]; //结束时的角度
    //    baseAnimation.autoreverses = NO;
    //    //动画终了后不返回初始状态
    //    baseAnimation.removedOnCompletion = NO;
    //    baseAnimation.fillMode = kCAFillModeForwards;
    //
    //    return baseAnimation;
    //}
    
    //沿y旋转
    - (CABasicAnimation *)rotationFromYWithDur:(float)duration {
        CABasicAnimation *baseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
        baseAnimation.duration = duration;
        baseAnimation.repeatCount = HUGE_VALF;  //重复不停
    //    baseAnimation.toValue = [NSNumber numberWithFloat:M_PI];
        baseAnimation.toValue = [NSNumber numberWithFloat:M_PI*2];
        baseAnimation.autoreverses = NO;
        //动画终了后不返回初始状态
        baseAnimation.removedOnCompletion = NO;
        baseAnimation.fillMode = kCAFillModeForwards;
        
        return baseAnimation;
    }
    

    //CATransition

    - (void)animationImageView {
        _animationIV = [[UIImageView alloc] initWithFrame:CGRectMake(10, 120, 100, 100)];
        _animationIV.image = [UIImage imageNamed:@"Yosemite00"];
        [self.view addSubview:_animationIV];
        
        UIButton *nextBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        nextBtn.frame = CGRectMake(80, 240, 40, 20);
        nextBtn.titleLabel.font = [UIFont systemFontOfSize:12];
        [nextBtn setTitle:@"next" forState:UIControlStateNormal];
        [nextBtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
        [nextBtn addTarget:self action:@selector(onNextBtn:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:nextBtn];
    }
    //转场动画: CATransition 单视图转场  双视图转场
    - (void)onNextBtn:(id)sender {
        self.index++;
        if (self.index >= 5) {
            self.index=0;
        }
        _animationIV.image = [UIImage imageNamed:[NSString stringWithFormat:@"Yosemite0%ld",(long)self.index]];
        
        //1.创建核心动画
        CATransition *caAnmation = [CATransition animation];
        //1.1告诉要执行什么动画
        //1.2设置过度效果
        caAnmation.type = @"cube";
        //1.3设置动画的过度方向(向右)
        caAnmation.subtype = kCATransitionFromRight;
        //1.4设置动画的时间
        caAnmation.duration = 2.0f;
        //1.5设置动画的起点
        caAnmation.startProgress = 0.5f;
        //1.6设置动画的终点
    //    caAnmation.endProgress = 0.0f;
        
        //2.添加动画
        [self.animationIV.layer addAnimation:caAnmation forKey:nil];
        
    }
    

    demo

    相关文章

      网友评论

          本文标题:iOS动画

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