[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的矩阵。
如下图所示:
x' = ax + cy + tx y' = xb + yd + ty z = 1不变; 也就是平面的变化,Z轴不变!
注意:
iOS中包含UIKit坐标系(X轴正方向向右,Y轴正方向向下)和标准的Quartz 2D绘图坐标系(X轴正方向向右,Y轴正方向向上)
因此,CGAffineTransform是一个3*3矩阵的变换。
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];
}