iOS CoreAnimation 關鍵幀動畫 CAKeyframeAnimation
效果:
關鍵幀動畫, 關鍵幀動畫就是在動畫控制過程中開發者指定主要的動畫狀態, 至於各種狀態間動畫如何進行則由系統自動運算補充(每個兩個關鍵幀之間系統形成的動畫成為補間動畫), 這種動畫的好處就是開發者不用逐個每個動畫幀, 而只關心幾個關鍵幀的狀態即可
關鍵幀動畫開發分為兩種形式, 一種是通過設定不同的屬性進行關鍵幀控制
另一種是通過繪製路徑進行關鍵幀控制, 後者優先順序高於前者, 如果設定了路徑則屬性就不再起作用
建立關鍵幀動畫的步驟:
// 1. 建立關鍵幀動畫 CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; [keyAnimation setValue:[NSValue valueWithCGPoint:CGPointMake(50, 614) ]forKey:@"LayerPosition"]; // 2. 設定貝塞爾曲線路徑 CGMutablePathRef path = CGPathCreateMutable(); // 設定易懂的起始點 CGPathMoveToPoint(path, NULL, _layer.position.x, _layer.position.y); // 繪製二次貝塞爾曲線 // 可以新增路徑, CGPathAddCurveToPoint(path, NULL, 160, 280, -30, 300, 50, 400); CGPathAddCurveToPoint(path, NULL, 160, 500, -30, 600, 50, 614); // 給動畫新增路徑 設定路徑屬性 keyAnimation.path = path; / // 記得釋放路徑 CGPathRelease(path); keyAnimation.calculationMode = kCAAnimationCubic; // 設定動畫其他屬性 keyAnimation.duration = 5.0; keyAnimation.removedOnCompletion = NO; keyAnimation.repeatCount = 1; keyAnimation.delegate = self; // 給圖層新增動畫 [_layer addAnimation:keyAnimation forKey:@"KCKeyAnimation_Positon"];
關於關鍵幀動畫路徑
如果路徑不是曲線的話,
矩形路徑是從矩形的左上角開始執行, 順時針執行一週回到最上角.
橢圓路徑的話就是從橢圓的右側開始(0度)順時針一週回到右側.
關於關鍵幀各個幀時間的屬性
keyTimes
各個關鍵幀的時間控制。前面使用values設定了四個關鍵幀,預設情況下每兩幀之間的間隔為:8/(4-1)秒。如果想要控制動畫從第一幀到第二針佔用時間4秒,從第二幀到第三幀時間為2秒,而從第三幀到第四幀時間2秒的話,就可以通過keyTimes進行設定。keyTimes中儲存的是時間佔用比例點,此時可以設定keyTimes的值為0.0,0.5,0.75,1.0(當然必須轉換為NSNumber),也就是說1到2幀執行到總時間的50%,2到3幀執行到總時間的75%,3到4幀執行到8秒結束。
caculationMode
動畫計算模式。還拿上面keyValues動畫舉例,之所以1到2幀能形成連貫性動畫而不是直接從第1幀經過8/3秒到第2幀是因為動畫模式是連續的
kCAAnimationLinear 這是計算模式的預設值
kCAAnimationDiscrete離散的那麼你會看到動畫從第1幀經過8/3秒直接到第2幀,中間沒有任何過渡
kCAAnimationPaced(均勻執行,會忽略keyTimes)、
kCAAnimationCubic(平滑執行,對於位置變動關鍵幀動畫執行軌跡更平滑
kCAAnimationCubicPaced
直接上程式碼,簡單易懂, 註釋很全:
//
// ViewController.m
// CAKeyframeAnimation
//
// Created by 帝炎魔 on 16/5/26.
// Copyright © 2016年 帝炎魔. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) CALayer *layer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 設定背景()
UIImage *backImage = [UIImage imageNamed:@"haha1"];
self.view.backgroundColor = [UIColor colorWithPatternImage:backImage];
// 自定義一個圖層
_layer = [[CALayer alloc] init];
_layer.bounds = CGRectMake(50, 50, 10, 20);
_layer.position = CGPointMake(50, 150);
_layer.contents = (id)[UIImage imageNamed:@"hudie"].CGImage;
[self.view.layer addSublayer:_layer];
// 建立動畫
[self translationKeyAnimation];
}
/**
* 關鍵幀動畫, 關鍵幀動畫就是在動畫控制過程中開發者指定主要的動畫狀態, 至於各種狀態間動畫如何進行則由系統自動運算補充(每個兩個關鍵幀之間系統形成的動畫成為補間動畫), 這種動畫的好處就是開發者不用逐個每個動畫幀, 而只關心幾個關鍵幀的狀態即可
關鍵幀動畫開發分為兩種形式, 一種是通過設定不同的屬性進行關鍵幀控制
另一種是通過繪製路徑進行關鍵幀控制, 後者優先順序高於前者, 如果設定了路徑則屬性就不再起作用
*/
/**
* 關於關鍵幀動畫路徑
* 如果路徑不是曲線的話,
矩形路徑是從矩形的左上角開始執行, 順時針執行一週回到最上角.
橢圓路徑的話就是從橢圓的右側開始(0度)順時針一週回到右側.
*/
/**
* keyTimes
*
各個關鍵幀的時間控制。前面使用values設定了四個關鍵幀,預設情況下每兩幀之間的間隔為:8/(4-1)秒。如果想要控制動畫從第一幀到第二針佔用時間4秒,從第二幀到第三幀時間為2秒,而從第三幀到第四幀時間2秒的話,就可以通過keyTimes進行設定。keyTimes中儲存的是時間佔用比例點,此時可以設定keyTimes的值為0.0,0.5,0.75,1.0(當然必須轉換為NSNumber),也就是說1到2幀執行到總時間的50%,2到3幀執行到總時間的75%,3到4幀執行到8秒結束。
*/
/**
* caculationMode
*
* 動畫計算模式。還拿上面keyValues動畫舉例,之所以1到2幀能形成連貫性動畫而不是直接從第1幀經過8/3秒到第2幀是因為動畫模式是連續的
kCAAnimationLinear 這是計算模式的預設值
kCAAnimationDiscrete離散的那麼你會看到動畫從第1幀經過8/3秒直接到第2幀,中間沒有任何過渡
kCAAnimationPaced(均勻執行,會忽略keyTimes)、
kCAAnimationCubic(平滑執行,對於位置變動關鍵幀動畫執行軌跡更平滑
kCAAnimationCubicPaced(平滑均勻執行)
*/
#pragma mark --- 關鍵幀動畫----> 設定關鍵幀的點座標執行動畫路徑
- (void)translationAnimation
{
// 1. 建立關鍵幀動畫物件 初始化keyPath
CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
// 2.設定關鍵幀, 有4個關鍵幀
// 對於關鍵幀動畫的初始值不能省略, 就是最少要有一個幀
NSValue *key1 = [NSValue valueWithCGPoint:_layer.position];
NSValue *key2 = [NSValue valueWithCGPoint:CGPointMake(80, 220)];
NSValue *key3 = [NSValue valueWithCGPoint:CGPointMake(45, 300)];
NSValue *key4 = [NSValue valueWithCGPoint:CGPointMake(55, 400)];
// 通喲keyTimes陣列來設定關鍵幀的執行時間
keyAnimation.keyTimes = @[@(0.1), @(0.2), @(0.3), @(1.0)];
NSArray *keys = @[key1, key2, key3, key4];
// 設定關鍵幀
keyAnimation.values = keys;
// 3. 設定其他屬性
keyAnimation.duration = 5.0;
keyAnimation.repeatCount = HUGE_VALF;
keyAnimation.removedOnCompletion = NO;
// 設定動畫的開始時間 延時兩秒執行
keyAnimation.beginTime = CACurrentMediaTime() + 2;
// 4.給圖層新增動畫
[_layer addAnimation:keyAnimation forKey:@"KCKeyframeAnimation_Position"];
}
#pragma mark ---- 關鍵幀動畫 ----> 設定貝塞爾曲線作為動畫執行的路徑
- (void)translationKeyAnimation
{
// 1. 建立關鍵幀動畫
CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
[keyAnimation setValue:[NSValue valueWithCGPoint:CGPointMake(50, 614) ]forKey:@"LayerPosition"];
// 2. 設定貝塞爾曲線路徑
CGMutablePathRef path = CGPathCreateMutable();
// 設定易懂的起始點
CGPathMoveToPoint(path, NULL, _layer.position.x, _layer.position.y);
// 繪製二次貝塞爾曲線
// 可以新增路徑,
CGPathAddCurveToPoint(path, NULL, 160, 280, -30, 300, 50, 400);
CGPathAddCurveToPoint(path, NULL, 160, 500, -30, 600, 50, 614);
// 給動畫新增路徑 設定路徑屬性
keyAnimation.path = path;
CGPathRelease(path);
keyAnimation.calculationMode = kCAAnimationCubic;
// 設定動畫其他屬性
keyAnimation.duration = 5.0;
keyAnimation.removedOnCompletion = NO;
keyAnimation.repeatCount = 1;
keyAnimation.delegate = self;
// 給圖層新增動畫
[_layer addAnimation:keyAnimation forKey:@"KCKeyAnimation_Positon"];
}
#pragma mark --- 動畫的代理方法
- (void)animationDidStart:(CAAnimation *)anim
{
}
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
// 開啟事務
[CATransaction begin];
// 關閉隱式動畫屬性
[CATransaction setDisableActions:YES];
_layer.position = [[anim valueForKey:@"LayerPosition"] CGPointValue];
[CATransaction commit];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end