一些很有用的参考,基本的讲解都可以在这里找到
系统的学习CoreAnimation可以看一下这本书
https://legacy.gitbook.com/book/zsisme/ios-/details
这本书的示例代码(本文不再写示例,大部分的示例可以在这里找到)
https://github.com/pflnh/CoreAnimationCode
还有苹果官方的guide
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40004514-CH1-SW1
CoreAnimation中的类结构
CAAnimation主要分为:转场动画(CATransition)、关键帧动画(CAKeyframeAnimation)、基本动画(CABasicAnimation)、组合动画(CAAnimationGroup)。
CAMediaTiming协议
@protocol CAMediaTiming
//对象的开始时间,指动画开始之前的的时间。默认是0.
@property CFTimeInterval beginTime;
//对象的持续时间,默认是0.
@property CFTimeInterval duration;
//图层的比率,用来衡量最初时间和当前时间。例如:如果比率为2,当前花费的时间就是最初时间的0.5。默认是1。
@property float speed;
/*时间轴偏移量。将时间轴移动至偏移位置,再执行整个动画时长。假设动画时长5秒,偏移量为13,
则开始位置为13 % 5 = 3,再执行一次动画时长5秒,即在时长位置3处结束。*/
@property CFTimeInterval timeOffset;
//重复次数
@property float repeatCount;
//对象的重复持续时间。默认是0。
@property CFTimeInterval repeatDuration;
//是否自动换向。如果为YES,那么动画执行完会按照原来的路径返回。默认是NO。
@property BOOL autoreverses;
/*决定当前对象过了非active时间段的行为. 比如动画开始之前、动画结束之后。
如果是CAAnimationd对象,则需要将其removedOnCompletion设置为NO,要不然fillMode不起作用
*/
@property(copy) NSString *fillMode;
@end
fillMode的各种可选值:
kCAFillModeRemoved 默认值。动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
kCAFillModeForwards 动画结束后,layer会一直保持着动画最后的状态
kCAFillModeBackwards 动画开始前,只要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始
kCAFillModeBoth 动画开始之前,layer处于动画初始状态,动画结束后layer保持动画最后的状态
1、转场动画(CATransition)
@interface CATransition : CAAnimation
/* 过渡动画名。当前合法的动画类型有:`fade', `moveIn', `push' and `reveal'. 默认是`fade'. */
@property(copy) NSString *type;
/* 一个可选择的动画子类型. 用来指定动画的运动方向,合法的值是: `fromLeft', `fromRight', `fromTop' and * `fromBottom'. */
@property(nullable, copy) NSString *subtype;
/* 这两个属性用来控制过渡动画的开始、结束执行过程,可以让动画停留在某个动画点上。合法的值是在0~1范围内。endProgress必须比startProgress的值要大。默认值是0—1.
*/
@property float startProgress;
@property float endProgress;
/*filter对象用来实现过渡动画。如果设置了filter,那么为layer设置的type和subtype属性将被忽略。*/
@property(nullable, strong) id filter;
@end
2、基本动画(CABasicAnimation)
CAPropertyAnimation是通过animationWithKeyPath方法来进行实例化的,所以CABasicAnimation、CAKeyframeAnimation都可以通过animationWithKeyPath的值来设定动画样式。
@interface CABasicAnimation : CAPropertyAnimation
@property(nullable, strong) id fromValue;//所改变属性的起始值
@property(nullable, strong) id toValue;//所改变属性的结束时的值
@property(nullable, strong) id byValue;//所改变属性相同起始值的改变量
@end
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"XXX"];
其中的keyPath可以在苹果的官方文档中找到所有的可选值。
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/AnimatableProperties/AnimatableProperties.html#//apple_ref/doc/uid/TP40004514-CH11-SW1
3、关键帧动画(CAKeyframeAnimation)
@interface CAKeyframeAnimation : CAPropertyAnimation
/*存储关键帧(keyframe)元素。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧。*/
@property(nullable, copy) NSArray *values;
/*设置CGPathRef\CGMutablePathRef,让layer跟着设定的路径移动。path只对CALayer的anchorPoint和position起作用。如果设置了path,values将被忽略。*/
@property(nullable) CGPathRef path;
/*为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是平均分配的。*/
@property(nullable, copy) NSArray *keyTimes;
/*速度控制函数,有kCAMediaTimingFunctionLinear、kCAMediaTimingFunctionEaseIn、kCAMediaTimingFunctionEaseOut、kCAMediaTimingFunctionEaseInEaseOut四种方式,默认是最后一种*/
@property(nullable, copy) NSArray *timingFunctions
/*计算模式。主要针对的是每一帧的内容为一个座标点的情况,也就是对anchorPoint 和 position 进行的动画。
目前提供如下几种模式:kCAAnimationLinear、kCAAnimationDiscrete 、kCAAnimationPaced
、kCAAnimationCubic 、kCAAnimationCubicPaced。*/
@property(copy) NSString *calculationMode;
/* 该值控制着曲线的紧密度(正值将越紧,负值将越宽松)*/
@property(nullable, copy) NSArray *tensionValues;
/*该值控制片段之间的链接(正值将有锋利的圆角,负值将是倒立的圆角)*/
@property(nullable, copy) NSArray *continuityValues;
/*该值定义了曲线发生的地点(正值将在控制点前移动曲线,负值将在控制点后移动)*/
@property(nullable, copy) NSArray *biasValues;
/*定义是否沿着路径旋转匹配对象动画路径切线,值可能为kCAAnimationRotateAuto和kCAAnimationRotateAutoReverse。默认是nil。如果没有路径对象,设置该属性值将无效,kCAAnimationRotateAutoReverse为了匹配正切将添加180°。*/
@property(nullable, copy) NSString *rotationMode;
@end
4、组合动画(CAAnimationGroup)
@interface CAAnimationGroup : CAAnimation
/* 存储CAAnimation对象的数组。数组的每一个元素在规定的duration时间内同时进行。*/
@property(nullable, copy) NSArray *animations;
@end
tips:在动画执行过程中,一般如果不加入任何设置动画会还原,可以使用以下方式来关闭这种效果。
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[CATransaction begin];
[CATransaction setDisableActions:YES];
[CATransaction commit];
UIView动画
1、UIViewAnimation
@interface UIView(UIViewAnimation)
//开始动画。传递的context值会传递给代理的start/did stop方法中。
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context;
//和beginAnimations方法成对出现。代表动画开始和执行,动画内容放在两个个方法中间。
+ (void)commitAnimations;
// 设置动画代理,当动画开始或者结束时会发消息给代理对象。默认是nil。
+ (void)setAnimationDelegate:(nullable id)delegate;
//动画即将开始时,执行selector,并且把beginAnimations:context:中传入的参数传进selector
+ (void)setAnimationWillStartSelector:(nullable SEL)selector;
//动画即将结束时,执行selector,并且把beginAnimations:context:中传入的参数传进selector
+ (void)setAnimationDidStopSelector:(nullable SEL)selector;
//动画的持续时间,以秒为单位。默认是0.2.
+ (void)setAnimationDuration:(NSTimeInterval)duration;
//动画延迟。默认是0。
+ (void)setAnimationDelay:(NSTimeInterval)delay;
//默认是now.
+ (void)setAnimationStartDate:(NSDate *)startDate;
//动画的节奏控制。默认是UIViewAnimationCurveEaseInOut。
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;
//动画重复次数。默认是0.
+ (void)setAnimationRepeatCount:(float)repeatCount;
//动画是否逆向运行。如果是YES的话,动画会按照原来的运动轨迹逆向返回。默认是NO。
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;
//动画是否从当前状态开始。默认是NO。如果为YES,那么动画在运行过程中当前视图的位置将会作为新的动画的开始状态。如果设置为NO,新动画将使用视图最後状态的位置作为开始状态。
+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;
//设置view的过渡效果, transition是设定过渡类型, cache为YES时代表使用视图缓存。
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;
//是否激活动画。如果是YES,就激活动画,当动画参数没有被激活那么动画属性的改变将被忽略。默认是YES。
+ (void)setAnimationsEnabled:(BOOL)enabled;
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) BOOL areAnimationsEnabled;
#else
+ (BOOL)areAnimationsEnabled;
#endif
+ (void)performWithoutAnimation:(void (NS_NOESCAPE ^)(void))actionsWithoutAnimation NS_AVAILABLE_IOS(7_0);
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) NSTimeInterval inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#else
+ (NSTimeInterval)inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#endif
@end
2、UIViewAnimationWithBlocks
@interface UIView(UIViewAnimationWithBlocks)
/**
block动画,可以设置动画时长、动画延迟、动画选项、动画结束状态、动画完成后最终状态,
可根据自己实际需要选择下面3种实现方式
**/
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0, completion = NULL
//视图过渡动画
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);
//视图间过渡动画
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // toView added to fromView.superview, fromView removed from its superview
//弹簧动画
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
//删除视图动画
+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray<__kindof UIView *> *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
@end
3、UIViewKeyframeAnimations
@interface UIView (UIViewKeyframeAnimations)
//设定动画时长、动画延迟、关键帧选项、关键帧
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
//添加关键帧动画的开始时间、帧动画在整个动画的比例
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0); // start time and duration are values between 0.0 and 1.0 specifying time and duration relative to the overall time of the keyframe animation
@end
UIView动画和CoreAnimation的关系
我们可以看以下这两篇文章
https://www.jianshu.com/p/72f4cca98b0e
https://www.jianshu.com/p/9e9c8ee3f7a2
UIVIew动画通过view.layer的action对象的actionForLayer:forKey:
来实现动画的。UIView动画就是对CoreAnimation动画的一种封装。同时我们也可以使用自定义的aciton对象来改变一些默认的隐式动画效果。