iOS动画

实现动画方法有很多种:图片动画最简单的是用数组放多张图片,用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动画)