UI基础--动画(缩放动画, 渐变动画, 左右振动, 移动动画, 组合动画)(封装好)

Posted Tracy-Mcgrady

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UI基础--动画(缩放动画, 渐变动画, 左右振动, 移动动画, 组合动画)(封装好)相关的知识,希望对你有一定的参考价值。

 

创建一个CAAnimation的类别 

CAAnimation+HCAnimation

.h

#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>

typedef NS_ENUM(NSInteger, Axis) {
    AxisX = 0,  ///< x轴
    AxisY,      ///< y轴
    AxisZ       ///< z轴
};

typedef NS_ENUM(NSInteger, ShakeDerection) {
    ShakeDerectionAxisX = 0,    ///< 左右
    ShakeDerectionAxisY,        ///< 上下
};

@interface CAAnimation (HCAnimation)

/**
 * 在具体的UIView上实现一个缩放的动画
 *@param   view         动画的载体
 *@param   scaleValue   最终缩放值
 *@param   repeat       动画循环次数,0表示无限循环
 *@param   duration     动画运行一次的时间
 *@return  void
 */
+ (void)showScaleAnimationInView:(UIView *)view ScaleValue:(CGFloat)scaleValue Repeat:(CGFloat)repeat Duration:(CGFloat)duration;

/**
 * 在具体的UIView上实现一个移动的动画
 *@param   view         动画的载体
 *@param   Position     最终停留的位置(中心点坐标)
 *@param   repeat       动画循环次数,0表示无限循环
 *@param   duration     动画运行一次的时间
 *@return  void
 */
+ (void)showMoveAnimationInView:(UIView *)view Position:(CGPoint)position Repeat:(CGFloat)repeat Duration:(CGFloat)duration;

/**
 * 在具体的UIView上实现一个旋转的动画
 *@param   view         动画的载体
 *@param   degree       旋转的弧度
 *@param   direction    旋转的方向
 *@param   repeat       动画循环次数,0表示无限循环
 *@param   duration     动画运行一次的时间
 *@return  void
 */
+ (void)showRotateAnimationInView:(UIView *)view Degree:(CGFloat)degree Direction:(Axis)direction Repeat:(CGFloat)repeat Duration:(CGFloat)duration;

/**
 * 在具体的UIView上实现一个透明度渐变的动画
 *@param   view         动画的载体
 *@param   alpha        最终显示的透明度
 *@param   repeat       动画循环次数,0表示无限循环
 *@param   duration     动画运行一次的时间
 *@return  void
 */
+ (void)showOpacityAnimationInView:(UIView *)view Alpha:(CGFloat)alpha Repeat:(CGFloat)repeat Duration:(CGFloat)duration;

/**
 * 在具体的UIView上实现一个震动的动画
 *@param   view         动画的载体
 *@param   offset       震动的偏移量
 *@param   derection    震动方向
 *@param   repeat       动画循环次数,0表示无限循环
 *@param   duration     动画运行一次的时间
 *@return  void
 */
+ (void)showShakeAnimationInView:(UIView *)view Offset:(CGFloat)offset Direction:(ShakeDerection)derection Repeat:(CGFloat)repeat Duration:(CGFloat)duration;

/**
 *清除具体UIView上的所有动画
 *@param   view   实施清除的对象
 *@return  void
 */
+ (void)clearAnimationInView:(UIView *)view;

@end

.m

#import "CAAnimation+HCAnimation.h"

@implementation CAAnimation (HCAnimation)

+ (void)showScaleAnimationInView:(UIView *)view ScaleValue:(CGFloat)scaleValue Repeat:(CGFloat)repeat Duration:(CGFloat)duration {
    
    if (repeat == 0) {
        repeat = MAXFLOAT;
    }
    CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    
    ///动画的起始状态值
    scaleAnimation.fromValue = [NSNumber numberWithFloat:1.0];
    ///动画结束状态值
    scaleAnimation.toValue = [NSNumber numberWithFloat:scaleValue];
    
    ///循环动画执行方式,原路返回式(YES 注意:一去一回才算一个动画周期) 还是 再次从头开始(NO 注意:仅仅去一次就是一个动画周期)
    scaleAnimation.autoreverses = YES;
    ///动画结束后保持的状态:开始状态(kCAFillModeRemoved/kCAFillModeBackwards)、结束状态(kCAFillModeForwards/kCAFillModeBoth)
    scaleAnimation.fillMode = kCAFillModeForwards;
    scaleAnimation.removedOnCompletion = NO;
    
    ///动画循环次数(MAXFLOAT 意味无穷)
    scaleAnimation.repeatCount = repeat;
    ///一个动画持续时间
    scaleAnimation.duration = duration;
    
    [view.layer addAnimation:scaleAnimation forKey:@"scaleAnimation"];
}

+ (void)showMoveAnimationInView:(UIView *)view Position:(CGPoint)position Repeat:(CGFloat)repeat Duration:(CGFloat)duration {
    
    if (repeat == 0) {
        repeat = MAXFLOAT;
    }
    CABasicAnimation *moveAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
    moveAnimation.fromValue = [NSValue valueWithCGPoint:view.layer.position];
    moveAnimation.toValue = [NSValue valueWithCGPoint:position];
    moveAnimation.autoreverses = YES;
    moveAnimation.fillMode = kCAFillModeForwards;
    moveAnimation.removedOnCompletion = NO;
    moveAnimation.repeatCount = repeat;
    moveAnimation.duration = duration;
    [view.layer addAnimation:moveAnimation forKey:@"moveAnimation"];
}

+ (void)showRotateAnimationInView:(UIView *)view Degree:(CGFloat)degree Direction:(Axis)direction Repeat:(CGFloat)repeat Duration:(CGFloat)duration {
    if (repeat == 0) {
        repeat = MAXFLOAT;
    }
    NSArray *axisArray = @[@"transform.rotation.x",@"transform.rotation.y",@"transform.rotation.z"];
    CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:axisArray[direction]];
    rotateAnimation.fromValue = [NSNumber numberWithFloat:0.0];
    rotateAnimation.toValue = [NSNumber numberWithFloat:degree];
    rotateAnimation.autoreverses = YES;
    rotateAnimation.fillMode = kCAFillModeForwards;
    rotateAnimation.removedOnCompletion = NO;
    rotateAnimation.repeatCount = repeat;
    rotateAnimation.duration = duration;
    [view.layer addAnimation:rotateAnimation forKey:@"rotateAnimation"];
}

+ (void)showOpacityAnimationInView:(UIView *)view Alpha:(CGFloat)alpha Repeat:(CGFloat)repeat Duration:(CGFloat)duration {
    if (repeat == 0) {
        repeat = MAXFLOAT;
    }
    CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"opacity"];
    animation.fromValue=[NSNumber numberWithFloat:1.0];
    animation.toValue=[NSNumber numberWithFloat:alpha];
    animation.repeatCount = repeat;
    animation.duration = duration;
    animation.removedOnCompletion=NO;
    animation.fillMode=kCAFillModeForwards;
    animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
    animation.autoreverses=YES;
    
    [view.layer addAnimation:animation forKey:@"animation"];
}

+ (void)showShakeAnimationInView:(UIView *)view Offset:(CGFloat)offset Direction:(ShakeDerection)derection Repeat:(CGFloat)repeat Duration:(CGFloat)duration {
    if (repeat == 0) {
        repeat = MAXFLOAT;
    }
    NSAssert([view.layer isKindOfClass:[CALayer class]] , @"invalid target");
    CGPoint originPos = CGPointZero;
    CGSize originSize = CGSizeZero;
    if ([view.layer isKindOfClass:[CALayer class]]) {
        originPos = [(CALayer *)view.layer position];
        originSize = [(CALayer *)view.layer bounds].size;
    }
    CAKeyframeAnimation* animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"position";
    //改变value来实现不同方向的震动
    CGFloat offsetX = 0;
    CGFloat offsetY = 0;
    if (derection == ShakeDerectionAxisX) {
        offsetX = offset;
    }else if (derection == ShakeDerectionAxisY){
        offsetY = offset;
    }
    animation.values = @[
                  [NSValue valueWithCGPoint:CGPointMake(originPos.x, originPos.y)],
                  [NSValue valueWithCGPoint:CGPointMake(originPos.x-offsetX, originPos.y-offsetY)],
                  [NSValue valueWithCGPoint:CGPointMake(originPos.x, originPos.y)],
                  [NSValue valueWithCGPoint:CGPointMake(originPos.x+offsetX, originPos.y+offsetY)],
                  [NSValue valueWithCGPoint:CGPointMake(originPos.x, originPos.y)]
                  ];
    animation.repeatCount = repeat;
    animation.duration = duration;
    animation.fillMode = kCAFillModeForwards;
    [view.layer addAnimation:animation forKey:@"animation"];
}

+ (void)clearAnimationInView:(UIView *)view {
    [view.layer removeAllAnimations];
}

@end

在需要的地方调用就可以了.

#import "ViewController.h"
#import "CAAnimation+HCAnimation.h"

#define kBtnTag             0
#define kBtnSelectedTag     1

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.btn1.tag = kBtnTag;
    self.btn2.tag = kBtnTag;
    self.btn3.tag = kBtnTag;
    self.btn4.tag = kBtnTag;
    self.btn5.tag = kBtnTag;
    self.btn6.tag = kBtnTag;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

///缩放动画
- (IBAction)btn1Clicked:(id)sender {
    UIButton *btn = (UIButton *)sender;
    if (btn.tag == kBtnTag) {
        [CAAnimation showScaleAnimationInView:btn ScaleValue:1.5 Repeat:0 Duration:0.8];
    }else{
        [CAAnimation clearAnimationInView:btn];
    }
    btn.tag = btn.tag == kBtnTag ? kBtnSelectedTag : kBtnTag;
}

///渐变动画
- (IBAction)btn2Clicked:(id)sender {
    UIButton *btn = (UIButton *)sender;
    if (btn.tag == kBtnTag) {
        [CAAnimation showOpacityAnimationInView:btn Alpha:0.1 Repeat:0 Duration:0.6];
    }else{
        [CAAnimation clearAnimationInView:btn];
    }
    btn.tag = btn.tag == kBtnTag ? kBtnSelectedTag : kBtnTag;
}

///左右震动动画
- (IBAction)btn3Clicked:(id)sender {
    UIButton *btn = (UIButton *)sender;
    if (btn.tag == kBtnTag) {
        [CAAnimation showShakeAnimationInView:btn Offset:10.0 Direction:ShakeDerectionAxisX Repeat:0 Duration:0.5];
    }else{
        [CAAnimation clearAnimationInView:btn];
    }
    btn.tag = btn.tag == kBtnTag ? kBtnSelectedTag : kBtnTag;
}

///移动动画
- (IBAction)btn4Clicked:(id)sender {
    UIButton *btn = (UIButton *)sender;
    if (btn.tag == kBtnTag) {
        [CAAnimation showMoveAnimationInView:btn Position:CGPointMake(btn.layer.position.x*2, btn.layer.position.y) Repeat:0 Duration:0.8];
    }else{
        [CAAnimation clearAnimationInView:btn];
    }
    btn.tag = btn.tag == kBtnTag ? kBtnSelectedTag : kBtnTag;
}

///组合动画
- (IBAction)btn5Clicked:(id)sender {
    UIButton *btn = (UIButton *)sender;
    if (btn.tag == kBtnTag) {
        [CAAnimation showScaleAnimationInView:btn ScaleValue:1.5 Repeat:0 Duration:1.0];
        [CAAnimation showOpacityAnimationInView:btn Alpha:0.3 Repeat:0 Duration:1.0];
        [CAAnimation showMoveAnimationInView:btn Position:self.btn1.layer.position Repeat:0 Duration:1.0];
        [CAAnimation showRotateAnimationInView:btn Degree:2*M_PI Direction:AxisZ Repeat:0 Duration:1.0];
    }else{
        [CAAnimation clearAnimationInView:btn];
    }
    btn.tag = btn.tag == kBtnTag ? kBtnSelectedTag : kBtnTag;
}

///旋转动画
- (IBAction)btn6Clicked:(id)sender {
    UIButton *btn = (UIButton *)sender;
    if (btn.tag == kBtnTag) {
        [CAAnimation showRotateAnimationInView:btn Degree:2*M_PI Direction:AxisY Repeat:0 Duration:1.0];
    }else{
        [CAAnimation clearAnimationInView:btn];
    }
    btn.tag = btn.tag == kBtnTag ? kBtnSelectedTag : kBtnTag;
}
@end

OK...

 

以上是关于UI基础--动画(缩放动画, 渐变动画, 左右振动, 移动动画, 组合动画)(封装好)的主要内容,如果未能解决你的问题,请参考以下文章

Flutter动画 --- 平移/旋转/缩放/渐变

Tween Animation---Scale渐变尺寸缩放动画

使用渐变缩放 UIView

79.Android之动画基础

Android 动画

自定义view实现阻尼效果的加载动画