引用官方文檔:html
Core Animation provides high frame rates and smooth animations without burdening the CPU and slowing down your app. Most of the work required to draw each frame of an animation is done for you. You configure animation parameters such as the start and end points, and Core Animation does the rest, handing off most of the work to dedicated graphics hardware, to accelerate rendering. For more details, see Core Animation Programming Guide.git
Core Animation
提供了高幀率和流暢的動畫,而不會加劇CPU負擔,也不會減慢應用程序的速度。你能夠配置動畫參數,如起始點和結束點,Core animation
完成其他部分,將大部分工做交給專用的圖形硬件,以加速渲染。github
對於CAAnimation
,是核心動畫基礎類,不直接使用,通常用它的子類。CAAnimation
有三個子類CAPropertyAnimation、CATransition、CAAnimationGroup
。第二個CATransition
是轉場動畫,第三個CAAnimationGroup
是動畫組。第一個CAPropertyAnimation
又分爲兩個子類CABasicAnimation、CAKeyframeAnimation
。CAKeyframeAnimation
是關鍵幀動畫。CABasicAnimation
下面還有個子類CASpringAnimation
是彈簧動畫。spring
CAPropertyAnimation
經過animationWithKeyPath
來建立動畫,能夠看看有哪些屬性能夠建立動畫。詳見官方文檔數組
anchorPoint
backgroundColor
backgroundFilters
borderColor
borderWidth
bounds
compositingFilter
contents
contentsRect
cornerRadius
doubleSided
filters
frame
hidden
mask
masksToBounds
opacity
position
shadowColor
shadowOffset
shadowOpacity
shadowPath
shadowRadius
sublayers
sublayerTransform
transform
zPosition
複製代碼
可使用繼承的animationWithKeyPath:
方法建立一個CAKeyframeAnimation
對象,並指定要在層上動畫的屬性的關鍵路徑。而後能夠指定用於控制時間和動畫行爲的關鍵幀值。對於大多數動畫類型,可使用值和keyTimes
屬性指定關鍵幀值。在動畫期間,Core animation
經過在您提供的值之間插入來生成中間值。當動畫一個座標點(例如layer的位置)的值時,你能夠指定該點的路徑,而不是單獨的值。動畫的節奏由你提供的時間信息控制。bash
屬性 | 描述 |
---|---|
values | 用來存放關鍵幀的數組 |
path | 基於點的屬性的路徑。 |
keyTimes | 對應關鍵幀段的時間點的NSNumber數組 |
timingFunctions | 關鍵幀動畫節奏的數組,好比快進慢出、慢進快出等 |
calculationMode | 肯定沿路徑動畫的對象是否旋轉以匹配路徑切線 |
tensionValues | 定義曲線的緊密性的NSNumber數組 |
continuityValues | 定義時間曲線銳角的NSNumber數組 |
biasValues | 定義曲線相對於控制點的位置的NSNumber數組 |
Rotation Mode Values | rotationMode屬性使用這些常量 |
Value calculation modes | calculationMode屬性使用這些常量 |
#pragma mark - 指定keyPath爲position,經過Values來建立關鍵幀動畫
- (void)CAKeyframeAnimationWithValues
{
CGFloat margin = 50.f;
CAKeyframeAnimation * animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
NSValue * value0 = [NSValue valueWithCGPoint:CGPointMake(margin, margin)];
NSValue * value1 = [NSValue valueWithCGPoint:CGPointMake(margin, SCREENHEIGHT - margin)];
NSValue * value2 = [NSValue valueWithCGPoint:CGPointMake(SCREENWIDTH - margin, SCREENHEIGHT - margin)];
NSValue * value3 = [NSValue valueWithCGPoint:CGPointMake(SCREENWIDTH - margin, margin)];
NSValue * value4 = [NSValue valueWithCGPoint:CGPointMake(margin, margin)];
animation.values = @[value0,value1,value2,value3,value4];
//當咱們動畫完成時,若是但願動畫就自動移除的話,咱們能夠設置此屬性爲YES,默認值爲YES
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
animation.duration = 4;
animation.repeatCount = MAXFLOAT;
//快入快出
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.pointView.layer addAnimation:animation forKey:@"position.values"];
}
#pragma mark - 指定keyPath爲position,經過path路徑來建立關鍵幀動畫
- (void)CAKeyframeAnimationWithPath
{
CGFloat margin = 50.f;
CAKeyframeAnimation * animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(margin, margin, SCREENWIDTH - margin * 2, SCREENHEIGHT - margin * 2));
animation.path = path;
CGPathRelease(path);
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
animation.duration = 4;
animation.repeatCount = MAXFLOAT;
NSMutableArray * timingFunctionArray = [NSMutableArray new];
for (NSInteger i = 0 ; i < 5 ; i ++)
{
//每一段都是快出效果
CAMediaTimingFunction * timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[timingFunctionArray addObject:timingFunction];
}
animation.timingFunctions = timingFunctionArray;
[self.pointView.layer addAnimation:animation forKey:@"position.path"];
}
複製代碼
須要注意的是removedOnCompletion設置爲NO的時候,不須要layer的時候要根據key手動移除動畫。app
[self.pointView.layer removeAnimationForKey:@"position.values"];
[self.pointView.layer removeAnimationForKey:@"position.path"];
複製代碼
CATransition
的父類是CAAnimation
,和CAPropertyAnimation
、CAAnimationGroup
同級。CATransition
是用來視圖的轉場動畫。dom
You can transition between a layer's states by creating and adding a CATransition object to it. The default transition is a cross fade, but you can specify different effects from a set of predefined transitions.ide
屬性 | 描述 |
---|---|
startProgress | 整個變形接收的起點 |
endProgress | 整個變形接收的終點 |
type | 指定轉換類型 |
subtype | 轉換方向的子類型 |
filter | 提供轉換的圖像過濾器對象 |
Common Transition Types | 指定能夠與type屬性一塊兒使用的轉換類型的常量 |
Common Transition Subtypes | 指定能夠與subtype屬性一塊兒使用的轉換類型的常量 |
其中type
和subtype
有官方指定的類型動畫
/* Common transition types. */
CA_EXTERN NSString * const kCATransitionFade
CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
CA_EXTERN NSString * const kCATransitionMoveIn
CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
CA_EXTERN NSString * const kCATransitionPush
CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
CA_EXTERN NSString * const kCATransitionReveal
CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
/* Common transition subtypes. */
CA_EXTERN NSString * const kCATransitionFromRight
CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
CA_EXTERN NSString * const kCATransitionFromLeft
CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
CA_EXTERN NSString * const kCATransitionFromTop
CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
CA_EXTERN NSString * const kCATransitionFromBottom
CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
複製代碼
還有幾種效果是私有API,在官方文檔中找不到,慎用
Cube, //立體
SuckEffect, //吮吸
OglFlip, //翻轉
RippleEffect, //波紋
PageCurl, //翻頁
PageUnCurl, //反翻頁
CameraIrisHollowOpen, //開鏡頭
CameraIrisHollowClose, //關鏡頭
複製代碼
這裏寫了一個例子,有12種type
轉場效果和4種subtype
轉場方向,用枚舉來封裝一下
typedef NS_ENUM(NSInteger,CATransactionType) {
CATransactionType_Fade = 0, //默認
CATransactionType_MoveIn, //覆蓋
CATransactionType_Push, //推入
CATransactionType_Reveal, //揭開
CATransactionType_Cube, //立體
CATransactionType_SuckEffect, //吮吸
CATransactionType_OglFlip, //翻轉
CATransactionType_RippleEffect, //波紋
CATransactionType_PageCurl, //翻頁
CATransactionType_PageUnCurl, //反翻頁
CATransactionType_CameraIrisHollowOpen, //開鏡頭
CATransactionType_CameraIrisHollowClose, //關鏡頭
};
- (void)CATransitionWithType:(NSString *)type WithSubtype:(NSString *)subtype
{
CATransition * animation = [CATransition animation];
animation.duration = 2.f;
animation.type = type;
animation.subtype = subtype;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.view.layer addAnimation:animation forKey:nil];
}
- (void)btnClick:(UIButton *)sender
{
UIButton * lastBtn;
NSInteger index = sender.tag - 100;
if (index > 11)
{
lastBtn = (UIButton *)[self.view viewWithTag:_subtype + 100];
[lastBtn setBackgroundImage:[self createImageWithColor:self.subtypeNormalColor] forState:UIControlStateNormal];
[sender setBackgroundImage:[self createImageWithColor:self.subtypeSelectedColor] forState:UIControlStateNormal];
_subtype = index;
}
else
{
lastBtn = (UIButton *)[self.view viewWithTag:_transactionType + 100];
[lastBtn setBackgroundImage:[self createImageWithColor:self.typeNormalColor] forState:UIControlStateNormal];
[sender setBackgroundImage:[self createImageWithColor:self.typeSelectedColor] forState:UIControlStateNormal];
_transactionType = index;
}
NSString * subtypeString ;
switch (_subtype % 4) {
case 0:
subtypeString = kCATransitionFromTop;
break;
case 1:
subtypeString = kCATransitionFromBottom;
break;
case 2:
subtypeString = kCATransitionFromLeft;
break;
case 3:
subtypeString = kCATransitionFromRight;
break;
default:
break;
}
switch (_transactionType) {
case CATransactionType_Fade:
[self CATransitionWithType:kCATransitionFade WithSubtype:subtypeString];
break;
case CATransactionType_MoveIn:
[self CATransitionWithType:kCATransitionMoveIn WithSubtype:subtypeString];
break;
case CATransactionType_Push:
[self CATransitionWithType:kCATransitionPush WithSubtype:subtypeString];
break;
case CATransactionType_Reveal:
[self CATransitionWithType:kCATransitionReveal WithSubtype:subtypeString];
break;
case CATransactionType_Cube:
[self CATransitionWithType:@"cube" WithSubtype:subtypeString];
break;
case CATransactionType_SuckEffect:
[self CATransitionWithType:@"suckEffect" WithSubtype:subtypeString];
break;
case CATransactionType_OglFlip:
[self CATransitionWithType:@"oglFlip" WithSubtype:subtypeString];
break;
case CATransactionType_RippleEffect:
[self CATransitionWithType:@"rippleEffect" WithSubtype:subtypeString];
break;
case CATransactionType_PageCurl:
[self CATransitionWithType:@"pageCurl" WithSubtype:subtypeString];
break;
case CATransactionType_PageUnCurl:
[self CATransitionWithType:@"pageUnCurl" WithSubtype:subtypeString];
break;
case CATransactionType_CameraIrisHollowOpen:
[self CATransitionWithType:@"cameraIrisHollowOpen" WithSubtype:subtypeString];
break;
case CATransactionType_CameraIrisHollowClose:
[self CATransitionWithType:@"cameraIrisHollowClose" WithSubtype:subtypeString];
break;
default:
break;
}
static NSInteger i = 0;
self.bgView.image = i % 2 ? [UIImage imageNamed:@"拉姆.jpeg"] :[UIImage imageNamed:@"蕾姆.jpeg"];
i ++;
}
複製代碼
分組動畫在CAAnimationGroup
實例指定的時間中運行。分組動畫的持續時間不會被縮放到他們的CAAnimationGroup
的持續時間。相反,動畫被剪切到動畫組的持續時間。例如,在一個動畫組中分組的10秒動畫,持續時間爲5秒,只顯示動畫的前5秒。
#pragma mark - 一個紅包雨的例子
- (void)showRain
{
UIImageView * imageV = [UIImageView new];
imageV.image = [UIImage imageNamed:@"page"];
imageV.frame = CGRectMake(0, 0, 50 , 50 );
CALayer * layer = [CALayer layer];
layer.bounds = imageV.frame;
layer.contents = (id)imageV.image.CGImage;
layer.anchorPoint = CGPointMake(0, 0);
layer.position = CGPointMake(0, 0);
[self.view.layer addSublayer:layer];
[self addAnimationWithLayer:layer];
}
- (void)addAnimationWithLayer:(CALayer *)layer
{
int height = [UIScreen mainScreen].bounds.size.height;
int width = [UIScreen mainScreen].bounds.size.height;
CAKeyframeAnimation * moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
NSValue * A = [NSValue valueWithCGPoint:CGPointMake(arc4random() % width, 0)];
NSValue * B = [NSValue valueWithCGPoint:CGPointMake(arc4random() % width, height + 100)];
moveAnimation.values = @[A,B];
moveAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
CAKeyframeAnimation * tranAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
CATransform3D r0 = CATransform3DMakeRotation(M_PI/180 * (arc4random() % 360 ) , 0, 0, -1);
CATransform3D r1 = CATransform3DMakeRotation(M_PI/180 * (arc4random() % 360 ) , 0, 0, -1);
tranAnimation.values = @[[NSValue valueWithCATransform3D:r0],[NSValue valueWithCATransform3D:r1]];
tranAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
CAAnimationGroup * group = [[CAAnimationGroup alloc] init];
group.duration = arc4random() % 200 / 100.0 + 3.5;
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
group.animations = @[moveAnimation,tranAnimation];
[layer addAnimation:group forKey:nil];
}
複製代碼
CASpringAnimation
的父類是CABasicAnimation
, CABasicAnimation
能夠當作是隻有頭尾有值的關鍵幀動畫。
You would typically use a spring animation to animate a layer's position so that it appears to be pulled towards a target by a spring. The further the layer is from the target, the greater the acceleration towards it is. CASpringAnimation allows control over physically based attributes such as the spring's damping and stiffness.
CASpringAnimation
是基於物理的屬性控制,好比彈簧的阻尼和剛度。
屬性 | 描述 |
---|---|
damping | 定義彈簧運動如何受到阻尼的影響 |
initialVelocity | 初速度 |
mass | 鏈接到彈簧末端的物體的質量 |
settlingDuration | 預估靜止時間 |
stiffness | 彈簧剛度係數 |
- (void)btnClick:(UIButton *)sender
{
//frame屬性不可動畫化 只能經過 bounds 和 position完成
CASpringAnimation * animation = [CASpringAnimation animationWithKeyPath:@"bounds"];
//質量,影響圖層運動時的彈簧慣性,質量越大,彈簧拉伸和壓縮的幅度越大
animation.mass = self.massSlider.value;
//剛度係數(勁度係數/彈性係數),剛度係數越大,形變產生的力就越大,運動越快
animation.stiffness = self.stiffnessSlider.value;
//阻尼係數,阻止彈簧伸縮的係數,阻尼係數越大,中止越快
animation.damping = self.dampingSlider.value;
//初始速率,動畫視圖的初始速度大小;速率爲正數時,速度方向與運動方向一致,速率爲負數時,速度方向與運動方向相反
animation.initialVelocity = self.velocitySlider.value;
animation.duration = 3.f;
animation.fromValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 80, 100)];
animation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 80, 240)];
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.baseView.layer addAnimation:animation forKey:nil];
CASpringAnimation * animation1 = [CASpringAnimation animationWithKeyPath:@"position"];
animation1.duration = 3.f;
animation1.fromValue = [NSValue valueWithCGPoint:CGPointMake(SCREENWIDTH / 2 , 250)];
animation1.toValue = [NSValue valueWithCGPoint:CGPointMake(SCREENWIDTH / 2 , 250 - 70)];
animation1.removedOnCompletion = NO;
animation1.fillMode = kCAFillModeForwards;
[self.baseView.layer addAnimation:animation1 forKey:nil];
}
複製代碼
另外在看看cell
上用UIView Block
彈簧動畫的特效
+ (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)cellAnimation
{
[self.springTableView reloadData];
NSArray * cellArrays = self.springTableView.visibleCells;
CGFloat height = self.springTableView.bounds.size.height;
for (UITableView * cell in cellArrays)
{
cell.transform = CGAffineTransformMakeTranslation(-SCREENWIDTH, height);
}
for (NSInteger i = 0 ; i < cellArrays.count ; i ++ )
{
UITableViewCell * cell = (UITableViewCell *)cellArrays[i];
[UIView animateWithDuration:1.5
delay:0.05 * i
usingSpringWithDamping:0.8
initialSpringVelocity:0
options:0 animations:^{
cell.transform = CGAffineTransformMakeTranslation(0, 0);
} completion:nil];
}
}
複製代碼