今天抽空大致介紹iOS開發中常見動畫的使用,及注意點:
下面以一張圖片總結一下iOS開發中常用動畫,
CALayer:隱式動畫
CATransaction :NSObject(區分下面的CATransition,他是繼承CATran)
[CATransaction begin];
[CATransaction setDisableActions:!enableAnimation.isOn];
[CATransaction setAnimationDuration:animationDuration.value];
[_layer setCornerRadius:[_layer cornerRadius]==0?30:0];
[_layer setBorderWidth:[_layer borderWidth]==0?5:0];
[_layer setBorderColor:[UIColor redColor].CGColor];
[CATransaction commit];
常用方法
- (void)begin;
- (void)commit;
- (void)flush;
- (void)lock;
- (void)unlock;
[UIView beginAnimations:@"animationID" context:nil];
[UIView setAnimationDuration:animationDuration.value];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationRepeatAutoreverses:enableAnimation.isOn];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:image cache:YES];
[UIView commitAnimations];
常用方法:
setAnimationDuration
+ (void)beginAnimations:(NSString *)animationID context:(void *)context;
+ (void)commitAnimations;
+ (void)setAnimationDuration:(NSTimeInterval)duration; // default = 0.2
+ (void)setAnimationDelay:(NSTimeInterval)delay; // default=now ([NSDate date])
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve; // default = UIViewAnimationCurveEaseInOut
+ (void)setAnimationRepeatCount:(float)repeatCount;
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache; // current limitation - only one per begin/commit block
Block動畫:
[UIView animateWithDuration:animationDuration.value delay:.5 options:UIViewAnimationOptionCurveEaseOut animations:^(void){
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:image cache:YES];
} completion:^(BOOL finish){
animationDurationLabel.text = @"動畫結束";
}];
常用方法
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0
UIViewKeyframeAnimations分類(非正式協議):
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(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
三:核心動畫

核心動畫中最基本的屬性與方法
+ (instancetype)animation;
+ (id)defaultValueForKey:(NSString *)key;
- (BOOL)shouldArchiveValueForKey:(NSString *)key;
@property(strong) CAMediaTimingFunction *timingFunction;
@property(strong) id delegate;
非正式協議:
- (void)animationDidStart:(CAAnimation *)anim;
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;
下面也是在官方文檔中關于核心動畫的一段話
CAAnimation is an abstract animation class. It provides the basic support for the CAMediaTiming and CAAction protocols. To animate Core Animation layers or Scene Kit objects, create instances of the concrete subclasses CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, or CATransition.
CATransition(轉場動畫)
繼承自:CAAnimation
CATransition *transtion = [CATransition animation];
[transtion setStartProgress:.2];
[transtion setEndProgress:.8];
transtion.duration = animationDuration.value;
[transtion setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[transtion setType:@"rippleEffect"];
[transtion setSubtype:kCATransitionFromTop];
[image.layer addAnimation:transtion forKey:@"transtionKey"];
常用屬性
@property(copy) NSArray *animations;
@property float startProgress;
@property float endProgress;
@property(strong) id filter;
duration:設置動畫時間
type:subtype:typetimingFunction ,,(),
轉場類型type:
Fade = 1, //淡入淡出
Push, //推擠
Reveal, //揭開
MoveIn, //覆蓋
Cube, //立方體
SuckEffect, //吮吸(水滴)
OglFlip, //翻轉
RippleEffect, //波紋
(默認以父類為參照,所以一般我們使用一個和子控件一樣大的父控件來修改這個效果)
PageCurl, //翻頁
PageUnCurl, //反翻頁
CameraIrisHollowOpen, //開鏡頭
CameraIrisHollowClose, //關鏡頭
CurlDown, //下翻頁
CurlUp, //上翻頁
FlipFromLeft, //左翻轉
FlipFromRight, //右翻轉
轉場子類型subtype:
kCAMediaTimingFunctionLinear 線性即勻速
kCAMediaTimingFunctionEaseIn 先慢后快
kCAMediaTimingFunctionEaseOut 先快后慢
kCAMediaTimingFunctionEaseInEaseOut 先慢后快再慢
kCAMediaTimingFunctionDefault 實際效果是動畫中間比較快
注意:轉場動畫與轉場代碼必須寫在一起,否則無效
CAPropertyAnimation動畫
CAPropertyAnimation(屬性動畫),是后面兩個動畫的父類
繼承自:CAAnimation
CAPropertyAnimation *pro = [CAPropertyAnimation animation];
pro.additive = YES;
pro.cumulative = YES;
pro.valueFunction = kCAValueFunctionScaleX;
[image.layer addAnimation:pro forKey:AnimationKey]
常用屬性
- (instancetype)animationWithKeyPath:(NSString *)path;
@property(copy) NSString *keyPath;
@property(getter=isAdditive) BOOL additive;
@property(getter=isCumulative) BOOL cumulative;
@property(strong) CAValueFunction *valueFunction;
CABasicAnimation(基本動畫)
繼承自;CAPropertyAnimation
CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
[basic setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
[basic setFromValue:[NSNumber numberWithFloat:1]];
[basic setToValue:[NSNumber numberWithFloat:.3]];
[basic setDuration:animationDuration.value];
[basic setDelegate:self];
[image.layer addAnimation:basic forKey:AnimationKey];
基本屬性
@property(strong) id fromValue;
@property(strong) id toValue;
@property(strong) id byValue;
CAKeyframeAnimation(關鍵幀)
繼承自;CAPropertyAnimation
1):values->
CAKeyframeAnimation *keyframe = [CAKeyframeAnimation animationWithKeyPath:@"borderWidth"];
keyframe.values = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0],
[NSNumber numberWithFloat:5],
[NSNumber numberWithFloat:10],
[NSNumber numberWithFloat:15],nil];
// keyframe.values = @[@12, @-12, @12];
keyframe.repeatCount = MAXFLOAT;
keyframe.autoreverses = enableAnimation.isOn;
keyframe.duration = animationDuration.value;
[image.layer addAnimation:keyframe forKey:AnimationKey];
2):paths->
UIBezierPath *path = [UIBezierPath bezierPath];
// [path moveToPoint:image.frame.origin];
[path moveToPoint:CGPointMake(image.frame.origin.x + image.frame.size.width/2, image.frame.origin.y + image.frame.size.height/2)];
[path addLineToPoint:CGPointMake(image.frame.origin.x + image.frame.size.width/2,400)];
[path addLineToPoint:CGPointMake(20, 400)];
CAKeyframeAnimation *keyframe = [CAKeyframeAnimation animationWithKeyPath:@"position"];
keyframe.path = path.CGPath;
keyframe.duration = animationDuration.value;
[image.layer addAnimation:keyframe forKey:AnimationKey];
常見屬性
@property(copy) NSArray *values;
@property CGPathRef path;
@property(copy) NSArray *keyTimes;
@property(copy) NSArray *timingFunctions;
@property(copy) NSString *calculationMode;
@property(copy) NSArray *tensionValues;
@property(copy) NSArray *continuityValues;
@property(copy) NSArray *biasValues;
@property(copy) NSString *rotationMode;
CAAnimationGroup(動畫組)
繼承自:CAAnimation
CAAnimationGroup *group = [CAAnimationGroup animation];
CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
[basic setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
[basic setFromValue:[NSNumber numberWithFloat:1]];
[basic setToValue:[NSNumber numberWithFloat:.3]];
CAKeyframeAnimation *keyframe = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.x"];
keyframe.values = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0],[NSNumber numberWithFloat:M_PI], nil];
[group setDuration:animationDuration.value];
[group setAnimations:[NSArray arrayWithObjects:basic,keyframe, nil]];
[image.layer addAnimation:group forKey:AnimationKey];
常見屬性
@property(copy) NSArray *animations;
@property(copy) NSString *fillMode;
fillMode
kCAFillModeForwards
kCAFillModeBackwards
kCAFillModeBoth
kCAFillModeRemoved
UIView動畫與核心動畫的區別,及使用注意的地方:
1:核心動畫的一切都是假象,并不會真實的修改layer對應的屬性
2:UIView必須修改真實屬性的值
使用-》
只要不需要與用戶交互就使用核心動畫,如果需要與用戶交互就使用UIView動畫
核心動畫的使用場景:轉場(核心動畫包裝的轉場動畫足夠強大)
3D動畫
下面來電更酷的3D動畫(結合以上技術)
[UIView animateWithDuration:animationDuration.value animations:^{
[UIView setAnimationRepeatCount:MAXFLOAT];
[UIView setAnimationRepeatAutoreverses:enableAnimation.isOn];
CATransform3D transform = CATransform3DMakeTranslation(0, -150, 0);
CATransform3D trans = CATransform3DScale(transform, 1.5, 1.5, 10);
[label.layer setTransform:trans];
} completion:^(BOOL finished) {
animationDurationLabel.text = @"finished";
}];
CABasicAnimation
CABasicAnimation *basic = [CABasicAnimation
animationWithKeyPath:@"transform.scale"];
[basic setDuration:animationDuration.value];
[basic setRepeatCount:MAXFLOAT];
[basic setAutoreverses:enableAnimation.isOn];
NSValue *valueForm = [NSValue
valueWithCATransform3D:CATransform3DIdentity];
CATransform3D transTo = CATransform3DMakeScale(.5, .5, 0);
NSValue *valueTo = [NSValue valueWithCATransform3D:transTo];
[basic setFromValue:valueForm];
[basic setToValue:valueTo];
[image.layer addAnimation:basic forKey:AnimationKey];
CAKeyframeAnimation
CAKeyframeAnimation *keyframe = [CAKeyframeAnimation
animationWithKeyPath:@"transform.scale"];
[keyframe setRepeatCount:MAXFLOAT];
[keyframe setDuration:animationDuration.value];
[keyframe setAutoreverses:enableAnimation.isOn];
CATransform3D transForm = CATransform3DIdentity;
CATransform3D transTo = CATransform3DMakeScale(.5, .5, 0);
NSValue *valueForm = [NSValue
valueWithCATransform3D:transForm];
NSValue *valueTo = [NSValue valueWithCATransform3D:transTo];
[keyframe setValues:[NSArray
arrayWithObjects:valueTo,valueForm,nil]];
[image.layer addAnimation:keyframe forKey:AnimationKey];
CABasicAnimation
CABasicAnimation *basic = [CABasicAnimation
animationWithKeyPath:@"transform"];
[basic setRepeatCount:MAXFLOAT];
[basic setDuration:animationDuration.value];
[basic setAutoreverses:enableAnimation.isOn];
NSValue *valueForm = [NSValue
valueWithCATransform3D:CATransform3DIdentity];
CGAffineTransform affine = CGAffineTransformMakeTranslation(0,
-150);
CATransform3D t = CATransform3DMakeAffineTransform(affine);
CATransform3D trans = CATransform3DScale(t, 1.5, 1.5, 10);
NSValue *valueTo = [NSValue valueWithCATransform3D:trans];
[basic setFromValue:valueForm];
[basic setToValue:valueTo];
[label.layer addAnimation:basic forKey:AnimationKey];
3D彈出和隱藏動畫效果:
//使用關鍵幀-3D動畫實現按鈕的彈出效果
CAKeyframeAnimation *popAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
popAnimation.duration = 0.4;
popAnimation.values = @[[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.01f, 0.01f, 1.0f)],
[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1f, 1.1f, 1.0f)],
[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.9f, 0.9f, 1.0f)],
[NSValue valueWithCATransform3D:CATransform3DIdentity]];
popAnimation.keyTimes = @[@0.2f, @0.5f, @0.75f, @1.0f];
popAnimation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[self.layer addAnimation:popAnimation forKey:nil];
//使用關鍵幀動畫實現隱藏效果
CAKeyframeAnimation *hideAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
hideAnimation.duration = 0.4;
hideAnimation.values = @[[NSValue
valueWithCATransform3D:CATransform3DMakeScale(1.1f, 1.1f, 1.0f)],
[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0f, 1.0f, 1.0f)],
[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.00f, 0.00f, 0.00f)]];
hideAnimation.keyTimes = @[@0.2f, @0.5f, @0.75f];
hideAnimation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
hideAnimation.delegate = self;
[self.layer addAnimation:hideAnimation forKey:nil];
注意:核心動畫中有一個協議需要注意的:CAMediaTiming
下面是協議對應的一些屬性(方法)
@property CFTimeInterval beginTime;
@property CFTimeInterval duration;
@property float speed;
@property CFTimeInterval timeOffset;
@property float repeatCount;
@property CFTimeInterval repeatDuration;
@property BOOL autoreverses;
@property(copy) NSString *fillMode;