屬性簡介
@interface CAKeyframeAnimation : CAPropertyAnimation
/* 提供關(guān)鍵幀數(shù)據(jù)的數(shù)組,數(shù)組中的每一個值都對應(yīng)一個關(guān)鍵幀旗笔。根據(jù)動畫類型(keyPath)的不同 彪置,
值的類型不同*/
@property(nullable, copy) NSArray *values;
/*基于點(diǎn)的屬性的路徑,即動畫屬性類型為CGPoint。如: position换团、anchorPoint悉稠、transform.translation等
如果為此屬性指定非空值,則會忽略values屬性*/
@property(nullable) CGPathRef path;
/* keyTimes的值與values中的值一一對應(yīng)指定關(guān)鍵幀在動畫中的時間點(diǎn)艘包,取值范圍為[0,1]的猛。當(dāng)keyTimes沒有設(shè)置的時候,
各個關(guān)鍵幀的時間是平分的*/
@property(nullable, copy) NSArray*keyTimes;
/*指定每個關(guān)鍵幀之間的動畫緩沖效果,timingFunctions.count = keyTimes.count-1*/
@property(nullable, copy) NSArray*timingFunctions;
/*關(guān)鍵幀間插值計算模式*/
@property(copy) NSString *calculationMode;
/*針對cubic 計算模式的動畫想虎,這些屬性提供對插值方案的控制卦尊。每個*關(guān)鍵幀都可以具有與之相關(guān)的
張力、連續(xù)性和偏差值舌厨,這些值的范圍在[-1,1]內(nèi)(這定義了Kochanek-*Bartels樣條岂却,見http://en.wikipedia.org/wiki/Kochanek-Bartels_spline)。
*tensionValues控制曲線的“緊密度”(正值更緊,負(fù)值更圓)躏哩。
*continuityValues控制段的連接方式(正值表示銳角署浩,負(fù)值表示倒角)。
*biasValues定義曲線發(fā)生的位置(正值在控制點(diǎn)之前移動曲線扫尺,負(fù)值在控制點(diǎn)之后移動它)筋栋。
*每個數(shù)組中的第一個值定義第一個控制點(diǎn)的切線的行為,第二個值控*制第二個點(diǎn)的切線正驻,依此類推弊攘。任何未指定的值都默認(rèn)為零
*(如果未指定,則給出Catmull-Rom樣條曲線)姑曙。
*/
@property(nullable, copy) NSArray*tensionValues;
@property(nullable, copy) NSArray*continuityValues;
@property(nullable, copy) NSArray *biasValues;
/*定義沿路徑動畫的對象是否旋轉(zhuǎn)以匹配路徑切線*/
@property(nullable, copy) NSString *rotationMode;
@end
關(guān)鍵幀動畫其實(shí)通過一組動畫類型的值(或者一個指定的路徑)和這些值對應(yīng)的時間節(jié)點(diǎn)以及各時間節(jié)點(diǎn)的過渡方式來控制顯示的動畫襟交。關(guān)鍵幀動畫可以通過path屬性和values屬性來設(shè)置動畫的關(guān)鍵幀。
通過path設(shè)置動畫
1.1 path只能控制CGPoint類型的動畫屬性伤靠。如position捣域、anchorPoint、transform.translation等
1.2 創(chuàng)建路徑時所有的MoveTo醋界、LineTo竟宋、CurveTo等方法是定的點(diǎn)都組成了動畫的關(guān)鍵幀提完⌒畏模可以通過keyTimes屬性賦值來控制關(guān)鍵幀的時間點(diǎn),通過timingFunctions屬性控制關(guān)鍵幀間的動畫
來控制動畫的顯示徒欣。
1.3 path屬性的優(yōu)先級高于values屬性優(yōu)先級逐样。當(dāng)path被賦非空值時,values屬性的值將被忽略打肝。
1.4 貝塞爾曲線可視工具:
http://yisibl.github.io/cubic-bezier/#.99,.01,1,.49
- (void)setPathAnimation
{
CGMutablePathRef path = CGPathCreateMutable();
//第一個關(guān)鍵幀 -100脂新,-100
CGPathMoveToPoint(path, NULL, -100, -100);
//第二個關(guān)鍵幀 100,-100
CGPathAddLineToPoint(path, NULL, 100, -100);
//第三個關(guān)鍵幀 100粗梭,100
CGPathAddLineToPoint(path, NULL, 100, 100);
//第四個關(guān)鍵幀 -100争便,100
CGPathAddLineToPoint(path, NULL, -100, 100);
//第五個關(guān)鍵幀 -100,-100
CGPathAddLineToPoint(path, NULL, -100, -100);
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"transform.translation";
animation.path = path;
animation.duration = 4;
animation.keyTimes = @[@(0),@(0.1),@(0.5),@(0.75),@(1)];
animation.timingFunctions = @[[CAMediaTimingFunction functionWithControlPoints:1 :0.5 :0.5 :0.5],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];
//動畫結(jié)束后保持動畫最后的狀態(tài)断医,兩個屬性需配合使用
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
CGPathRelease(path);
[self.layer addAnimation:animation forKey:@""];
}
通過values設(shè)置動畫
2.1 values指定了一組離散的關(guān)鍵幀滞乙,這些關(guān)鍵幀之間的需要通過插值來進(jìn)行過渡。這些插值計算方式calculationMode設(shè)置鉴嗤。
2.2 網(wǎng)上看到有說calculationMode適用于anchorPoint 和 position等坐標(biāo)點(diǎn)類型的屬性斩启,在查閱官方文檔及代碼測試,這種說法并不成立醉锅。calculationMode的插值計算方式同樣適用于backgroundColor兔簇、opacity等非坐標(biāo)點(diǎn)類型的動畫屬性
關(guān)鍵字 | 屬性 |
---|---|
kCAAnimationLinear | calculationMode的默認(rèn)值,關(guān)鍵幀之間直接直線相連進(jìn)行插值計算 |
kCAAnimationDiscrete | 離散的,就是不進(jìn)行插值計算,所有關(guān)鍵幀直接逐個進(jìn)行顯示。values數(shù)組長度比keyTimes數(shù)組長度小1,每一個keyTime對表示當(dāng)前關(guān)鍵幀的起始時間和下一關(guān)鍵幀的起始時間垄琐,在keyTime對的時間內(nèi)边酒,物體停留在當(dāng)前關(guān)鍵幀指定的位置 |
kCAAnimationPaced | 插入線性關(guān)鍵幀,動畫以恒定速度運(yùn)行狸窘。同時忽略keyTimes和timingFunctions設(shè)置 |
kCAAnimationCubic | 對關(guān)鍵幀為進(jìn)行圓滑曲線相連后插值計算,對于曲線的形狀還可以通過tensionValues, continuityValues, biasValues來進(jìn)行自定義調(diào)整,這里的數(shù)學(xué)原理是Kochanek–Bartels spline,這里的主要目的是使得運(yùn)行的軌跡變得圓滑; |
kCAAnimationCubicPaced | 看這個名字就知道和kCAAnimationCubic有一定聯(lián)系,其實(shí)就是在kCAAnimationCubic的基礎(chǔ)上使得動畫運(yùn)行變得均勻,就是系統(tǒng)時間內(nèi)運(yùn)動的距離相同,此時keyTimes以及timingFunctions也是無效的甚纲。對于曲線的形狀也可以使用tensionValues,continuityValues,biasValues來進(jìn)行調(diào)整 |
- (void)setValuesAnimation
{
CGPoint center = self.view.center;
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
animation.duration = 4;
animation.repeatCount = CGFLOAT_MAX;
animation.delegate = self;
// 計算方式1: kCAAnimationLinear 直線相連進(jìn)行插值計算
animation.calculationMode = kCAAnimationLinear;
animation.values = @[[NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y-100)],
[NSValue valueWithCGPoint:CGPointMake(center.x+100, center.y-100)],
[NSValue valueWithCGPoint:CGPointMake(center.x+100, center.y+100)],
[NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y+100)],
[NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y-100)]];
animation.keyTimes = @[@(0),@(0.25),@(0.5),@(0.75),@(1)];
animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];
// 計算方式2: kCAAnimationDiscrete。 無插值計算values.count = keyTimes.count-1;
// animation.calculationMode = kCAAnimationDiscrete;
// animation.values = @[[NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y-100)], //關(guān)鍵幀1開始時間0*duration=第0s
// [NSValue valueWithCGPoint:CGPointMake(center.x+100, center.y-100)], //關(guān)鍵幀2開始時間0.25*duration=第1s
// [NSValue valueWithCGPoint:CGPointMake(center.x+100, center.y+100)], //關(guān)鍵幀3開始時間0.5*duration=第2s
// [NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y+100)]]; //關(guān)鍵幀4開始時間0.75*duration=第3s 在第4秒動畫結(jié)束
// animation.keyTimes = @[@(0),@(0.25),@(0.5),@(0.75),@(1)];
// 計算方式3: kCAAnimationPaced朦前。 關(guān)鍵幀間直線相連進(jìn)行插值計算介杆,動畫以恒定速度運(yùn)行,忽略keyTimes韭寸、timingFunctions;
// animation.calculationMode = kCAAnimationPaced;
// animation.values = @[[NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y-100)],
// [NSValue valueWithCGPoint:CGPointMake(center.x+100, center.y-100)],
// [NSValue valueWithCGPoint:CGPointMake(center.x+100, center.y+100)],
// [NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y+100)],
// [NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y-100)]];
// 計算方式4: kCAAnimationCubic春哨。 關(guān)鍵幀間曲線相連進(jìn)行插值計算
// animation.calculationMode = kCAAnimationCubic;
// animation.values = @[[NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y-100)],
// [NSValue valueWithCGPoint:CGPointMake(center.x+100, center.y-100)],
// [NSValue valueWithCGPoint:CGPointMake(center.x+100, center.y+100)],
// [NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y+100)],
// [NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y-100)]];
// //然而知道該如何精確操作
// animation.tensionValues = @[@(1),@(0),@(0),@(0),@(0)];
// animation.continuityValues = @[@(-1),@(1),@(-1),@(1),@(-1)];
// animation.biasValues= @[@(1),@(1),@(1),@(1),@(1)];
// 計算方式5: kCAAnimationCubic。關(guān)鍵幀間曲線相連進(jìn)行插值計算恩伺,動畫以恒定速度運(yùn)行赴背,忽略keyTimes、timingFunctions;
// animation.calculationMode = kCAAnimationCubicPaced;
// animation.values = @[[NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y-100)],
// [NSValue valueWithCGPoint:CGPointMake(center.x+100, center.y-100)],
// [NSValue valueWithCGPoint:CGPointMake(center.x+100, center.y+100)],
// [NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y+100)],
// [NSValue valueWithCGPoint:CGPointMake(center.x-100, center.y-100)]];
// animation.keyTimes = @[@(0),@(0.25),@(0.5),@(0.75),@(1)];
// animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
// [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],
// [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut],
// [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];
// //然而知道該如何精確操作
// animation.tensionValues = @[@(1),@(0),@(0),@(0),@(0)];
// animation.continuityValues = @[@(-1),@(1),@(-1),@(1),@(-1)];
// animation.biasValues= @[@(1),@(1),@(1),@(1),@(1)];
[self.layer addAnimation:animation forKey:@""];
if (!_displayLink) {
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
}
如有大神碰巧路過晶渠,發(fā)現(xiàn)問題請進(jìn)行指正
demo地址:
https://gitee.com/dbmxl/KeyframeAnimation
參考文章:
http://www.iosxxx.com/blog/2015-11-01-coreanimationdong-hua-ru-men.html
http://www.reibang.com/p/22333040616e