[TOC]

2.CAPropertyAnimation

CAPropertyAnimation是属性动画,通常不直接使用,而是使用子类:

//属性动画:通常不直接使用,而是使用子类
  @interface CAPropertyAnimation : CAAnimation
    //1.基本属性动画:提供了对单一动画的实现,比如位置从A到B,然后就会移动过去。
    @interface CABasicAnimation : CAPropertyAnimation   
        @interface CASpringAnimation : CABasicAnimation  //弹簧动画

    //2.关键桢动画,可以定义动画路线,例如在A和B之间,会根据一定的算法布一些位置。
    @interface CAKeyframeAnimation : CAPropertyAnimation
  • 1) CABasicAnimation: 提供了对单一动画的实现,比如位置从A到B,然后就会移动过去。
  • 2) CAKeyframeAnimation: 关键桢动画,可以定义动画路线,比如A,B,C,D4个位置,然后A和B之间,会根据一定的算法布一些位置。还可以按照提供的路径进行动画。
  • 3) CASpringAnimation(iOS9.0+) 继承于CABaseAnimation,用于制作弹簧动画。

API

//创建属性动画  
@interface CAPropertyAnimation : CAAnimation 

+ (instancetype)animationWithKeyPath:(nullable NSString *)path;
//参数path只是一个字符串,指定CALayer的属性
//The key-path describing the property to be animated.

@property(nullable, copy) NSString *keyPath;//对应上面的KeyPath;指定动画的属性

@property(getter=isAdditive) BOOL additive; //设置该属性动画是否以当前动画效果为基础
@property(getter=isCumulative) BOOL cumulative; //指定动画是否为累加效果
@property(nullable, strong) CAValueFunction *valueFunction; //该属性值是一个CAValueFunction对象,该对象负责对属性改变的插值计算,系统已经提供了默认的插值计算方式,因此一般无须指定该属性。

@end



@interface CABasicAnimation : CAPropertyAnimation //基础属性动画三个属性

@property(nullable, strong) id fromValue; //从多少
@property(nullable, strong) id toValue; //到多少   
@property(nullable, strong) id byValue; //增加多少

@end



@interface CAKeyframeAnimation : CAPropertyAnimation

  @property(nullable, copy) NSArray *values;
  @property(nullable) CGPathRef path; 
  //作用与values属性一样,同样是用于指定整个动画所经过的路径的;可以设置一个CGPathRef、CGMutablePathRef
  //需要注意的是,values与path是互斥的,当values与path同时指定时,path会覆盖values,即values属性将被忽略
  //path只对CALayer的anchorPoint和position属性起作用

  @property(nullable, copy) NSArray<NSNumber *> *keyTimes; //指定每个阶段的时间,默认平均
  @property(nullable, copy) NSArray<CAMediaTimingFunction *> *timingFunctions; //指定每个阶段运动的加速度
  @property(nullable, copy) NSArray<NSNumber *> *tensionValues;
  @property(nullable, copy) NSArray<NSNumber *> *continuityValues;
  @property(nullable, copy) NSArray<NSNumber *> *biasValues;

  @property(copy) NSString *calculationMode; //指定每个阶段是跳着走还是匀速走
  @property(nullable, copy) NSString *rotationMode;

@end

// kCAAnimationRotateAutoReverse
CA_EXTERN NSString * const kCAAnimationLinear;/线性,默认
CA_EXTERN NSString * const kCAAnimationDiscrete;//离散
CA_EXTERN NSString * const kCAAnimationPaced;//平均
CA_EXTERN NSString * const kCAAnimationCubic;//平均
CA_EXTERN NSString * const kCAAnimationCubicPaced;//平均

// Rotation Mode Values
CA_EXTERN NSString * const kCAAnimationRotateAuto;
CA_EXTERN NSString * const kCAAnimationRotateAutoReverse;



@interface CASpringAnimation : CABasicAnimation //用于制作弹簧动画。继承基本属性动画

@property CGFloat mass; //质量,质量越大,弹簧拉伸和压缩的幅度越大;但动画的速度变慢
@property CGFloat stiffness;//刚度系数,刚度系数越大,形变产生的力就越大,运动越快。
@property CGFloat damping;//阻尼系数,阻尼系数越大,停止越快。
@property CGFloat initialVelocity;//初始速率,初始速度为正数时,速度方向与运动方向一致,速率为负数时,速度方向与运动方向相反。
@property(readonly) CFTimeInterval settlingDuration; //弹簧动画到停止时的估算时间。通常弹簧动画的时间使用结算时间比较准确

@end

💯属性动画的路径

对于属性动画,就是通过改变CALayer的属性来实现的动画:==常用的属性如下==

@property CGPoint position;  //移动动画常用
@property CGFloat zPosition;
@property CGPoint anchorPoint;
@property CGFloat anchorPointZ;

@property CGFloat borderWidth;
@property CGRect bounds;
@property CGRect frame;

@property CATransform3D transform; //平面和三维动画:平移 旋转 缩放
@property CATransform3D sublayerTransform;

@property float opacity; //透明度变化动画


@property(nullable, copy) NSArray *filters; //滤镜动画
@property(nullable, copy) NSArray *backgroundFilters;

等等......
1. 一维: piont:CGPath & UIBezierPath   ———> 主要对应CALayer的属性: position
2. 平面: X,Y两个维度:CGAffineTransform   ———> 对应CALayer的属性: transform 
3. 三维空间: X,Y,Z三个维度:CATransform3D   ———> 对应CALayer的属性: transform

1. 位移: CGPath & UIBezierPath

如果要控制CALayer的位移动画,直接使用属性动画控制CALayer的position持续改变即可。

主要涉及的类:CGPath & UIBezierPath;创造 点 线 曲线(贝塞尔曲线) 矩形 圆弧 圆 椭圆

2. 平面维度: CGAffineTransform

CGAffineTransform对象(变换矩阵),该对象代表CALayer执行 X,Y两个维度(平面))上的 旋转,缩放,位移,斜切,镜像 等变换矩阵。

CGAffineTransform是一个可以和二维空间向量(例如CGPoint)做乘法的3X2的矩阵。称为仿射变换,“仿射”的意思是无论变换矩阵用什么值,图层中平行的两条线在变换之后任然保持平行”。

官方定义:

struct CGAffineTransform {
    CGFloat a, b, c, d;
    CGFloat tx, ty;
};

虽然结构体中只有a,b,c,d,tx,ty 6个参数,但其实还有3个固定的参数[0,0,1]来组成3x3的矩阵。

如下图所示:

图5.1

x' = ax + cy + tx y' = xb + yd + ty z = 1不变; 也就是平面的变化,Z轴不变!

注意:

iOS中包含UIKit坐标系(X轴正方向向右,Y轴正方向向下)和标准的Quartz 2D绘图坐标系(X轴正方向向右,Y轴正方向向上)

因此,CGAffineTransform是一个3*3矩阵的变换。

img

struct CGAffineTransform {
    CGFloat a, b, c, d;
    CGFloat tx, ty;
};



# Creating an Affine Transformation Matrix
//CGAffineTransformMake
//CGAffineTransformMakeRotation
//CGAffineTransformMakeScale
//CGAffineTransformMakeTranslation


//The identity transform: [ 1 0 0 1 0 0 ].
//恒等变换
CG_EXTERN const CGAffineTransform CGAffineTransformIdentity;

//Return the transform [ a b c d tx ty ]. 
//直接创建变换
CG_EXTERN CGAffineTransform CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty);

//Return a transform which translates by `(tx, ty)': t' = [ 1 0 0 1 tx ty ] 
//平移:设置平移量
CG_EXTERN CGAffineTransform CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty) ;

//Return a transform which scales by `(sx, sy)':t' = [ sx 0 0 sy 0 0 ]
//缩放:设置缩放比例
//CGAffineTransformMakeScale(-1.0, 1.0);//水平翻转
//CGAffineTransformMakeScale(1.0,-1.0);//垂直翻转
CG_EXTERN CGAffineTransform CGAffineTransformMakeScale(CGFloat sx, CGFloat sy);

//Return a transform which rotates by `angle' radians: t' = [ cos(angle) sin(angle) -sin(angle) cos(angle) 0 0 ]
//旋转:设置旋转角度
CG_EXTERN CGAffineTransform CGAffineTransformMakeRotation(CGFloat angle);


# Modifying Affine Transformations
//CGAffineTransformTranslate
//CGAffineTransformScale
//CGAffineTransformRotate
//CGAffineTransformInvert
//CGAffineTransformConcat


//Return true if `t' is the identity transform, false otherwise.
//检测一个Transformation是不是恒等变换,也就是说不变
CG_EXTERN bool CGAffineTransformIsIdentity(CGAffineTransform t);

//Translate `t' by `(tx, ty)' and return the result: t' = [ 1 0 0 1 tx ty ] * t
//为一个变换再加上平移
CG_EXTERN CGAffineTransform CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty) ;

//Scale `t' by `(sx, sy)' and return the result: t' = [ sx 0 0 sy 0 0 ] * t
//为一个Transformation再加上缩放
CG_EXTERN CGAffineTransform CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy);

//Rotate `t' by `angle' radians and return the result: t' =  [ cos(angle) sin(angle) -sin(angle) cos(angle) 0 0 ] * t
//为一个Transformation再加上旋转
CG_EXTERN CGAffineTransform CGAffineTransformRotate(CGAffineTransform t, CGFloat angle) ;

//Invert `t' and return the result. If `t' has zero determinant, then `t' is returned unchanged.
//返回Transformation的反向
CG_EXTERN CGAffineTransform CGAffineTransformInvert(CGAffineTransform t);

//Concatenate `t2' to `t1' and return the result: t' = t1 * t2
//合并两个Transformation
CG_EXTERN CGAffineTransform CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);

//Return true if `t1' and `t2' are equal, false otherwise.
//检测两个Transformation是否相等
CG_EXTERN bool CGAffineTransformEqualToTransform(CGAffineTransform t1, CGAffineTransform t2);



# Applying Affine Transformations
//CGPointApplyAffineTransform
//CGSizeApplyAffineTransform
//CGRectApplyAffineTransform

//Transform `point' by `t' and return the result: p' = p * t  where p = [ x y 1 ].
//把变化应用到一个点上
CG_EXTERN CGPoint CGPointApplyAffineTransform(CGPoint point, CGAffineTransform t);

//Transform `size' by `t' and return the result: s' = s * t where s = [ width height 0 ].
//运用到一个区域中
CG_EXTERN CGSize CGSizeApplyAffineTransform(CGSize size, CGAffineTransform t);

//Transform `rect' by `t' and return the result. Since affine transforms do not preserve rectangles in general, this function returns the smallest rectangle which contains the transformed corner points of `rect'. If `t' consists solely of scales, flips and translations, then the returned rectangle coincides with the rectangle constructed from the four transformed corners.
//运用到一个带原点的区间
CG_EXTERN CGRect CGRectApplyAffineTransform(CGRect rect, CGAffineTransform t);



/*** Definitions of inline functions. **

CG_INLINE CGAffineTransform
__CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d,
                        CGFloat tx, CGFloat ty)
{
    CGAffineTransform t;
    t.a = a; t.b = b; t.c = c; t.d = d; t.tx = tx; t.ty = ty;
    return t;
}
#define CGAffineTransformMake __CGAffineTransformMake

CG_INLINE CGPoint
__CGPointApplyAffineTransform(CGPoint point, CGAffineTransform t)
{
    CGPoint p;
    p.x = (CGFloat)((double)t.a * point.x + (double)t.c * point.y + t.tx);
    p.y = (CGFloat)((double)t.b * point.x + (double)t.d * point.y + t.ty);
    return p;
}
#define CGPointApplyAffineTransform __CGPointApplyAffineTransform

CG_INLINE CGSize
__CGSizeApplyAffineTransform(CGSize size, CGAffineTransform t)
{
    CGSize s;
    s.width = (CGFloat)((double)t.a * size.width + (double)t.c * size.height);
    s.height = (CGFloat)((double)t.b * size.width + (double)t.d * size.height);
    return s;
}

3. 三维: CATransform3D

如果要控制CALayer的3D动画,直接使用CALayer的transform属性。

transform: 该属性值指定一个CATransform3D对象,该对象代表对CALayer执行X,Y,Z三个维度(三维空间)中的旋转,缩放,位移,斜切,镜像等变换矩阵。很明显如果只是对CALayer进行平面上的变换,指定普通的affineTransform属性即可,如果要对CALayer执行三维空间的变化,则需要指定transform属性。

CATransform3D:就是下面的结构体

三维坐标系(X,Y,Z轴):

struct CATransform3D
{
  CGFloat m11, m12, m13, m14;
  CGFloat m21, m22, m23, m24;
  CGFloat m31, m32, m33, m34;
  CGFloat m41, m42, m43, m44;
};

其中(m11, m12, m13,m21, m22, m23,m31, m32, m33)将会组成变换矩阵,m14,m24,m34,m44只是占位符,通常m14,m24,m34会设置为0.m14设置为1.假如变换前的店坐标为(x,y,z),与该矩阵相乘后得到变换后该点的坐标。按矩阵相乘算法

[x,y,z].(m11,m12,m13

​ m21,m22,m23=(xm11+ym21+zm31 xm12+ym22+zm32 xm13+ym23+z*m33)

         m31,m32,m33)

上面公式计算出来的坐标还要加上tx,ty,tz这3个X,Y,Z方向的偏移量。因此对于点(x,y,z)经过CATransform3D变换后,该点的实际坐标为(xm11+ym21+zm31+tx xm12+ym22+zm32+ty xm13+ym23+z*m33+tz).

一般来说可以使用 Core Animation提供的如下函数来创建三维变换矩阵:

//The identity transform: [1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1].
CA_EXTERN const CATransform3D CATransform3DIdentity;

//Returns true if 't' is the identity transform. 判断t矩阵是否为单位矩阵 
CA_EXTERN bool CATransform3DIsIdentity (CATransform3D t);

//Returns true if 'a' is exactly equal to 'b'. 判断两个变换矩阵是否相等
CA_EXTERN bool CATransform3DEqualToTransform (CATransform3D a, CATransform3D b);

//Returns a transform that translates by '(tx, ty, tz)':  t' =  [1 0 0 0; 0 1 0 0; 0 0 1 0; tx ty tz 1].
//创建在x方向上移动tx,在y方向上移动ty,在z方向上移动tz的变换矩阵。
CA_EXTERN CATransform3D CATransform3DMakeTranslation (CGFloat tx, CGFloat ty, CGFloat tz);

//Returns a transform that scales by `(sx, sy, sz)':  t' = [sx 0 0 0; 0 sy 0 0; 0 0 sz 0; 0 0 0 1].
//创建在x方向上缩放tx,在y方向上缩放ty,在z方向上缩放tz的变换矩阵。
CA_EXTERN CATransform3D CATransform3DMakeScale (CGFloat sx, CGFloat sy, CGFloat sz);

//Returns a transform that rotates by 'angle' radians about the vector  '(x, y, z)'. If the vector has length zero the identity transform is returned.
//创建基于指定旋转轴旋转angle弧度的变换,其中x,y,z用于确定旋转轴的方向。比如 (1,0,0)指定旋转轴为x轴,(1,1,0)指定以x,y轴夹角的中线为旋转轴。
CA_EXTERN CATransform3D CATransform3DMakeRotation (CGFloat angle, CGFloat x, CGFloat y, CGFloat z);

//Translate 't' by '(tx, ty, tz)' and return the result: t' = translate(tx, ty, tz) * t.
//以已有t变换矩阵为基础进行位移变换。
CA_EXTERN CATransform3D CATransform3DTranslate (CATransform3D t, CGFloat tx, CGFloat ty, CGFloat tz);

//Scale 't' by '(sx, sy, sz)' and return the result: t' = scale(sx, sy, sz) * t.
//以已有t变换矩阵为基础进行缩放变换。
CA_EXTERN CATransform3D CATransform3DScale (CATransform3D t, CGFloat sx, CGFloat sy, CGFloat sz);

//Rotate 't' by 'angle' radians about the vector '(x, y, z)' and return the result. If the vector has zero length the behavior is undefined: t' = rotation(angle, x, y, z) * t.
//以已有t变换矩阵为基础进行旋转变换。
CA_EXTERN CATransform3D CATransform3DRotate (CATransform3D t, CGFloat angle, CGFloat x, CGFloat y, CGFloat z);

//Concatenate 'b' to 'a' and return the result: t' = a * b. 
//对a变换矩阵进行累加
CA_EXTERN CATransform3D CATransform3DConcat (CATransform3D a, CATransform3D b);

//Invert 't' and return the result. Returns the original matrix if 't' has no inverse.
//对已有的t变换矩阵执行反转。
CA_EXTERN CATransform3D CATransform3DInvert (CATransform3D t);

//Return a transform with the same effect as affine transform 'm'. 
//将CGAffineTransform矩阵包装成为CATransform3D变换矩阵,该CATransform3D也只有x,y维度变换。
CA_EXTERN CATransform3D CATransform3DMakeAffineTransform (CGAffineTransform m);

//Returns true if 't' can be represented exactly by an affine transform. 
//如果t变换矩阵只有一个CGAffineTransform矩阵,则改函数返回YES.
CA_EXTERN bool CATransform3DIsAffine (CATransform3D t);

//Returns the affine transform represented by 't'. If 't' can not be represented exactly by an affine transform the returned value is undefined.
//获取t变换矩阵所包含的CGAffineTransform变换矩阵。
CA_EXTERN CGAffineTransform CATransform3DGetAffineTransform (CATransform3D t);



//NSValue support.
@interface NSValue (CATransform3DAdditions)

  + (NSValue *)valueWithCGAffineTransform:(CGAffineTransform)transform;
  @property(nonatomic, readonly) CGAffineTransform CGAffineTransformValue;


  + (NSValue *)valueWithCATransform3D:(CATransform3D)t;
  @property(readonly) CATransform3D CATransform3DValue;

@end

应1用

代码参见:“demo_XYAnim”。

1. CABasicAnimation

//一维:position
- (void)test01 {
    //基础动画两种实例化方式
    CABasicAnimation *basicAnimation=[CABasicAnimation animationWithKeyPath:@"position"];
    //CABasicAnimation *basicAnimation=[CABasicAnimation animation];
    //basicAnimation.keyPath = @"position";

    //基础动画主要有三个属性 fromValue, toValue, byValue
    //toValue到多少
    //byValue增加多少
    //这几个属性都是id类型,由于CGPoint是结构体类型,不能直接用,所以要转换一下下
    CGPoint fromPoint =self.imgv.layer.position;
    CGPoint toPoint =CGPointMake(fromPoint.x+80 , fromPoint.y+80);
    basicAnimation.fromValue = [NSValue valueWithCGPoint:fromPoint];
    basicAnimation.toValue = [NSValue valueWithCGPoint:toPoint];

    //动画共有的一些属性
    basicAnimation.duration=5.0;
    // 延迟3秒执行
    // basicAnimation.beginTime = CACurrentMediaTime()+3;

    //动画是添加到图层上的,动画结束后是否移除该动画 如果YES,fillMode属性基本没意义
    basicAnimation.removedOnCompletion=YES;
    //设置动画的状态
    //kCAFillModeForwards:动画延迟结束开始执行动画时从fromValue到toValue最终停留在toValue
    //kCAFillModeBackwards:动画在fromValue后开始延迟,延迟结束执行动画,从fromValue到toValue,最终到初始值状态
    //kCAFillModeBoth:动画在fromValue后开始延迟,延迟结束执行动画,从fromValue到toValue,最终到toValue
    //kCAFillModeRemoved:动画延迟结束开始执行动画时从fromValue到toValue最终停留在初始值状态
    //basicAnimation.fillMode=kCAFillModeRemoved;

    //设置动画的代理
    basicAnimation.delegate=self;

    self.imgv.layer.position = toPoint; //设置移动后图片的位置。

    //在图层中增加动画
    [self.imgv.layer addAnimation:basicAnimation forKey:nil];
}

//平面:affineTransform
- (void)test02 {
    //创建
    //注意:layer没有affineTransform属性
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"transform"];

    CGAffineTransform fromValue = self.imgv.layer.affineTransform;
    //设置动画开始的属性值
    anim.fromValue = [NSValue valueWithCGAffineTransform:fromValue];
    //平面动画:
    CGAffineTransform xuanzhuan = CGAffineTransformRotate(fromValue, M_PI);
    CGAffineTransform suofang = CGAffineTransformScale(xuanzhuan, 0.5, -0.5);
    CGAffineTransform pingyi = CGAffineTransformTranslate(suofang, 100, 100);
    //设置动画结束的属性值
    anim.toValue = [NSValue valueWithCGAffineTransform:pingyi];
    anim.duration = 5.0;
    self.imgv.layer.affineTransform = pingyi; //终点设置
    anim.removedOnCompletion =YES;
    //添加动画
    [self.imgv.layer addAnimation:anim forKey:nil];
}

//三维
- (void)test03 {
    //创建不断改变CALayer的transform属性的属性动画
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"transform"];

    CATransform3D fromValue = self.imgv.layer.transform;
    //设置动画开始的属性值
    anim.fromValue = [NSValue valueWithCATransform3D:fromValue];

    //三位动画
    CATransform3D pingyi = CATransform3DTranslate(fromValue, -100, -100, -100);
    CATransform3D xuanzhuan = CATransform3DRotate(pingyi, M_PI, 0.5, 0.5, 0.5);
    CATransform3D suofang = CATransform3DScale(xuanzhuan, -0.5, 0.5, 0.5);
    anim.toValue = [NSValue valueWithCATransform3D:suofang];
    // 绕X轴旋转180度
    //CATransform3D toValue =CATransform3DRotate(fromValue, M_PI , 1 , 0 , 0);
    // 绕Y轴旋转180度
    // CATransform3D toValue = CATransform3DRotate(fromValue, M_PI , 0 , 1 , 0);
    // // 绕Z轴旋转180度
    // CATransform3D toValue = CATransform3DRotate(fromValue, M_PI , 0 , 0 , 1);
    //设置动画结束的属性值

    anim.duration =5.0;
    self.imgv.layer.transform = suofang; //终点设置
    anim.removedOnCompletion =YES;
    //添加动画
    [self.imgv.layer addAnimation:anim forKey:nil];

}

//透明度:opacity
-(void)test04 {
    CABasicAnimation *opAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
    opAnim.duration = 3.0;
    opAnim.fromValue = [NSNumber numberWithFloat:0.25];
    opAnim.toValue= [NSNumber numberWithFloat:1.0];
    opAnim.cumulative = YES;
    opAnim.repeatCount = 2;
    [self.imgv.layer addAnimation:opAnim forKey:@"animateOpacity"];


    CABasicAnimation *moveAnim = [CABasicAnimation animationWithKeyPath:@"transform"];
    CGAffineTransform moveTransform = CGAffineTransformMakeTranslation(180, 200);
    moveAnim.duration = 6.0;
    moveAnim.toValue= [NSValue valueWithCATransform3D: CATransform3DMakeAffineTransform(moveTransform)];
    [self.imgv.layer addAnimation:moveAnim forKey:@"animateTransform"];
}

2.2CAKeyframeAnimation

//一维
- (void)test {
    NSLog(@"%s",__func__);
    //创建
    CAKeyframeAnimation* anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];

    //设定关键帧位置,必须含起始与终止位置
    CGPoint ori = self.imgv.layer.position;
    anim.values = [NSArray arrayWithObjects:
                   [NSValue valueWithCGPoint:ori],
                   [NSValue valueWithCGPoint:CGPointMake(ori.x+30, ori.y+0)],
                   [NSValue valueWithCGPoint:CGPointMake(ori.x+0, ori.y+30)],
                   [NSValue valueWithCGPoint:CGPointMake(ori.x+30, ori.y+30)],
                   [NSValue valueWithCGPoint:CGPointMake(ori.x-30, ori.y-0)],
                   [NSValue valueWithCGPoint:CGPointMake(ori.x+0, ori.y-30)],nil];
    anim.duration =5.0f;
    anim.removedOnCompletion =YES;
    [self.imgv.layer addAnimation:anim forKey:nil];
}

//二维
- (void)test02 {
    NSLog(@"%s",__func__);
    //创建
    //注意:layer没有affineTransform属性
    CAKeyframeAnimation* anim = [CAKeyframeAnimation animationWithKeyPath:@"transform"];

    //设置CAKeyframeAnimation控制affineTransform属性依次变化
    CGAffineTransform affine = self.imgv.layer.affineTransform;
    anim.values = [NSArray arrayWithObjects:
                   [NSValue valueWithCATransform3D:CATransform3DMakeAffineTransform(affine)],
                   [NSValue valueWithCATransform3D:CATransform3DMakeAffineTransform(CGAffineTransformMakeRotation(M_PI))],
                   [NSValue valueWithCATransform3D:CATransform3DMakeAffineTransform(CGAffineTransformMakeTranslation(100, 500))],
                   [NSValue valueWithCATransform3D:CATransform3DMakeAffineTransform(CGAffineTransformMakeScale(0.5, 0.7))],nil];
    anim.duration =5.0;
    anim.removedOnCompletion =YES;
    [self.imgv.layer addAnimation:anim forKey:nil];
}

//三维
- (void)test03 {
    NSLog(@"%s",__func__);
    //创建
    CAKeyframeAnimation* anim = [CAKeyframeAnimation animationWithKeyPath:@"transform"];

    //设置CAKeyframeAnimation控制transform属性依次经过的属性值
    anim.values = [NSArray arrayWithObjects:
                   [NSValue valueWithCATransform3D:self.imgv.layer.transform],
                   [NSValue valueWithCATransform3D:CATransform3DScale(self.imgv.layer.transform ,0.2, 0.2, 1)],
                   [NSValue valueWithCATransform3D:CATransform3DRotate(self.imgv.layer.transform, M_PI, 100, -50, -30)],
                   [NSValue valueWithCATransform3D:CATransform3DTranslate(self.imgv.layer.transform, 100, -50, -30)],
                   [NSValue valueWithCATransform3D:self.imgv.layer.transform],nil];
    anim.duration =5;
    anim.removedOnCompletion =YES;
    [self.imgv.layer addAnimation:anim forKey:nil];
}

//路径方式
- (void)testPath {
    //对于CAKeyframeAnimation而言,它除了可通过values属性指定动画过程中的多个值之外,
    //还可以通过path属性指定CALayer的移动路径,作用与values属性一样;可以设置一个CGPathRef、CGMutablePathRef
    //需要注意的是,values与path是互斥的,当values与path同时指定时,path会覆盖values,即values属性将被忽略
    //path只对CALayer的anchorPoint和position属性起作用
    //创建动画
    CAKeyframeAnimation* anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];

    //创建路径
    CGFloat x = self.imgv.layer.position.x;
    CGFloat y = self.imgv.layer.position.y;

    CGMutablePathRef movePath = CGPathCreateMutable();
    CGPathMoveToPoint(movePath, NULL, x, y);
    CGPathAddLineToPoint(movePath, NULL, x+100, y+100);
    CGPathAddEllipseInRect(movePath, NULL, CGRectMake(30, 300, 150, 150));
    CGPathAddArc(movePath,nil, 170, 175, 150, -M_PI /2, M_PI * 3 / 2, YES);

    anim.path = movePath;
    CGPathRelease(movePath);

    anim.duration = 5;
    anim.removedOnCompletion = YES;

    //添加动画
    [self.imgv.layer addAnimation:anim forKey:nil];
}

//透明度
-(void)test05 {
    CAKeyframeAnimation *opAnim = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];

    opAnim.values =[NSArray arrayWithObjects:
                    [NSNumber numberWithFloat:0.25],
                    [NSNumber numberWithFloat:0.75],
                    [NSNumber numberWithFloat:1.0],
                    nil];
    //时间点
    opAnim.duration = 6.0;

    //设定每个关键帧的时长,如果没有显式地设置,则默认每个帧的时间=总duration/(values.count - 1)
    opAnim.keyTimes = [NSArray arrayWithObjects:
                       [NSNumber numberWithFloat:0.0],
                       [NSNumber numberWithFloat:0.5],
                       [NSNumber numberWithFloat:1.0], nil];

    opAnim.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
                               [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
                               [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];

    [self.imgv.layer addAnimation:opAnim forKey:@"animateOpacity"];


    CABasicAnimation *moveAnim = [CABasicAnimation animationWithKeyPath:@"transform"];
    moveAnim.duration = 6.0;
    CGAffineTransform moveTransform = CGAffineTransformMakeTranslation(180, 200);
    moveAnim.toValue= [NSValue valueWithCATransform3D:
                       CATransform3DMakeAffineTransform(moveTransform)];
    [self.imgv.layer addAnimation:moveAnim forKey:@"animateTransform"];
}

2.3CASpringAnimation

//弹簧动画X
- (void)test01 {
    //弹簧动画
    //继承自基本属性动画CABasicAnimation

    //CASpringAnimation * animation = [CASpringAnimation animation];
    //animation.keyPath = @"position.x";
    CASpringAnimation *animation = [CASpringAnimation animationWithKeyPath:@"position.x"];

    //弹簧属性设置
    animation.mass = 10;
    animation.stiffness = 100;
    animation.damping = 1;
    animation.initialVelocity = 0;
    animation.duration = animation.settlingDuration; //等于预估时间

    //继承自基本属性动画CABasicAnimation
    animation.fromValue = [NSValue valueWithCGPoint:self.imgv.layer.position];
    animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(self.imgv.layer.position.x+100, self.imgv.layer.position.y)];
    //添加动画
    [self.imgv.layer addAnimation:animation forKey:animation.keyPath];
}

//弹簧动画Y
- (void)test02 {
    CASpringAnimation * animation = [CASpringAnimation animation];
    animation.keyPath = @"position.y";

    //弹簧属性设置
    animation.mass = 5;
    animation.stiffness = 100;
    animation.damping = 1;
    animation.initialVelocity = 0;
    animation.duration = animation.settlingDuration; //等于预估时间

    //继承自基本属性动画CABasicAnimation
    animation.fromValue = [NSValue valueWithCGPoint:self.imgv.layer.position];
    animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(self.imgv.layer.position.x, self.imgv.layer.position.y+100)];
    //添加动画
    [self.imgv.layer addAnimation:animation forKey:animation.keyPath];

}

results matching ""

    No results matching ""