一、簡介
- CABasicAnimation是
CAPropertyAnimation的子類, CAPropertyAnimation有一個(gè)字符串類型的keyPath屬性

keyPath內(nèi)容是CALayer的可動(dòng)畫Animatable屬性,可動(dòng)畫屬性可見CAlayer篇我們可以指定CALayer的某個(gè)屬性名為
keyPath,并且對(duì)CALayer的這個(gè)屬性的值進(jìn)行修改,達(dá)到相應(yīng)的動(dòng)畫效果。例如:指定keyPath = @"position",就會(huì)修改CALayer的position屬性的值,- > 可以實(shí)現(xiàn)平移的動(dòng)畫效果
屬性說明: fromValue:keyPath相應(yīng)屬性的初始值,toValue:keyPath相應(yīng)屬性的結(jié)束值
因此,初始化好CAPropertyAnimation的子類對(duì)象后,必須先設(shè)置keyPath(修改的是CALayer的哪個(gè)屬性)-> 指明執(zhí)行的是怎樣的動(dòng)畫(平移/縮放/旋轉(zhuǎn)等)
隨著動(dòng)畫的進(jìn)行,在長度為
duration的持續(xù)時(shí)間內(nèi),keyPath相應(yīng)屬性的值從fromValue漸漸地變?yōu)?code>toValuekeyPath內(nèi)容是CALayer的可動(dòng)畫Animatable屬性如果
fillMode=kCAFillModeForwards同時(shí)removedOnComletion=NO,那么在動(dòng)畫執(zhí)行完畢后,圖層會(huì)保持顯示動(dòng)畫執(zhí)行后的狀態(tài)。但在實(shí)質(zhì)上,圖層的屬性值還是動(dòng)畫執(zhí)行前的初始值,并沒有真正被改變。
屬性說明:
duration
動(dòng)畫時(shí)長fromValue
動(dòng)畫起始的位置,根據(jù)keyPath的值不一樣,這里的值也不一樣;比如keyPath是position的時(shí)候,fromValue的值就是[NSValue valueWithCGPoint:<#(CGPoint)#>];toValue
動(dòng)畫結(jié)束位置,和fromValue的值一致repeatCount
動(dòng)畫執(zhí)行次數(shù)Autoreverses
當(dāng)你設(shè)定這個(gè)屬性為 YES 時(shí),在它到達(dá)目的地之后,動(dòng)畫的返回到開始的值,代替了直接跳轉(zhuǎn)到 開始的值。removedOnCompletion
這個(gè)是在動(dòng)畫結(jié)束后,是否會(huì)回到開始的值,默認(rèn)是YES。如果設(shè)置為NO,則動(dòng)畫結(jié)束后,會(huì)保持動(dòng)畫結(jié)束后的形態(tài),但layer的相關(guān)屬性值并沒有改變Duration
Duration 這個(gè)參數(shù)你已經(jīng)相當(dāng)熟悉了。它設(shè)定開始值到結(jié)束值花費(fèi)的時(shí)間。期間會(huì)被速度的屬性所影響。RemovedOnCompletion這個(gè)屬性默認(rèn)為 YES,那意味著,在指定的時(shí)間段完成后,動(dòng)畫就自動(dòng)的從層上移除了。這個(gè)一般不用。
假如你想要再次用這個(gè)動(dòng)畫時(shí),你需要設(shè)定這個(gè)屬性為 NO。這樣的話,下次你在通過-set 方法設(shè)定動(dòng)畫的屬 性時(shí),它將再次使用你的動(dòng)畫,而非默認(rèn)的動(dòng)畫。
Speed
默認(rèn)的值為 1.0.這意味著動(dòng)畫播放按照默認(rèn)的速度。如果你改變這個(gè)值為 2.0,動(dòng)畫會(huì)用 2 倍的速度播放。 這樣的影響就是使持續(xù)時(shí)間減半。如果你指定的持續(xù)時(shí)間為 6 秒,速度為 2.0,動(dòng)畫就會(huì)播放 3 秒鐘---一半的 持續(xù)時(shí)間。BeginTime
這個(gè)屬性在組動(dòng)畫中很有用。它根據(jù)父動(dòng)畫組的持續(xù)時(shí)間,指定了開始播放動(dòng)畫的時(shí)間。默認(rèn)的是 0.0.組 動(dòng)畫在下個(gè)段落中討論“Animation Grouping”。TimeOffset
如果一個(gè)時(shí)間偏移量是被設(shè)定,動(dòng)畫不會(huì)真正的可見,直到根據(jù)父動(dòng)畫組中的執(zhí)行時(shí)間得到的時(shí)間都流逝 了。RepeatCount
默認(rèn)的是 0,意味著動(dòng)畫只會(huì)播放一次。如果指定一個(gè)無限大的重復(fù)次數(shù),使用 1e100f。這個(gè)不應(yīng)該和 repeatDration 屬性一塊使用。RepeatDuration
這個(gè)屬性指定了動(dòng)畫應(yīng)該被重復(fù)多久。動(dòng)畫會(huì)一直重復(fù),直到設(shè)定的時(shí)間流逝完。它不應(yīng)該和 repeatCount 一起使用。
keyPath屬性說明:
transform.scale = 比例轉(zhuǎn)換
transform.rotation = 旋轉(zhuǎn)
transform.rotation.x = x軸旋轉(zhuǎn)
transform.rotation.y = y軸旋轉(zhuǎn)
opacity = 透明度
margin = 邊距
position = 位移
backgroundColor = 背景顏色
cornerRadius = 圓角
borderWidth = 邊框?qū)挾?br>
bounds = 位置,體積
contents = 內(nèi)容
contentsRect = 面積
frame = 位置,體積
hidden = 是否隱藏
shadowColor = 陰影顏色
shadowOffset = 陰影偏移
shadowOpacity = 陰影透明
shadowRadius = 陰影半徑
CABasicAnimation應(yīng)用:
直線進(jìn)度條:
/*直線進(jìn)度條*/
- (CAShapeLayer *)lineAnimationLayer
{
if(!_lineAnimationLayer){
_lineAnimationLayer = [CAShapeLayer layer];
_lineAnimationLayer.strokeColor = [UIColor greenColor].CGColor;
_lineAnimationLayer.lineWidth = 5;
// 設(shè)置路徑
UIBezierPath * path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(50, 200)];
[path addLineToPoint:CGPointMake(300, 200)];
_lineAnimationLayer.path = path.CGPath;
/*動(dòng)畫,keyPath是系統(tǒng)定的關(guān)鍵詞,可以自己去幫助文檔里面查看*/
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
// animation的動(dòng)畫時(shí)長
animation.duration = 4.0;
// 動(dòng)畫的其實(shí)位置
animation.fromValue = @(0);
// 動(dòng)畫的結(jié)束位置
animation.toValue = @(1);
// 動(dòng)畫執(zhí)行次數(shù)
animation.repeatCount = MAXFLOAT;
// 添加動(dòng)畫并設(shè)置key;這個(gè)key值是自己定義的
[_lineAnimationLayer addAnimation:animation forKey:@"lineAnimationLayer"];
}
return _lineAnimationLayer;
}
執(zhí)行結(jié)果:

邊框環(huán)繞效果
實(shí)現(xiàn)代碼:
/**
* 跑馬燈二(shaperLayer)
*/
-(void)marquee2{
//創(chuàng)建一個(gè)shaperLayer
CAShapeLayer *shaperLayer = [CAShapeLayer layer];
shaperLayer.bounds = CGRectMake(0, 0, 10, 5);
shaperLayer.position = CGPointMake((kWidth-300)/2, (kHeight-200)/2);
shaperLayer.strokeColor = [UIColor whiteColor].CGColor;
shaperLayer.fillColor = [UIColor clearColor].CGColor;
shaperLayer.lineDashPattern = @[@(10),@(10)];
// 虛線結(jié)尾處的類型
shaperLayer.lineCap = kCALineCapRound;
// 拐角處layer的類型
shaperLayer.lineJoin = kCALineJoinRound;
shaperLayer.lineWidth = 5;
//創(chuàng)建動(dòng)畫路徑
UIBezierPath * path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 300, 200)];
shaperLayer.path = path.CGPath;
// CGPathRelease(path.CGPath);
CAKeyframeAnimation *animation2 = [CAKeyframeAnimation animationWithKeyPath:@"strokeEnd"];
animation2.duration = 8;
animation2.repeatCount = MAXFLOAT;
animation2.values = @[@(0),@(1),@(0)];
animation2.removedOnCompletion = NO;
animation2.fillMode = kCAFillModeForwards;
/**
* 上述的animation2的動(dòng)畫和效果和下面的animation動(dòng)畫效果是一樣的
*/
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.duration = 4;
animation.repeatCount = MAXFLOAT;
animation.fromValue = @(0);
animation.toValue = @(1);
// 這個(gè)設(shè)置是在一個(gè)動(dòng)畫完成時(shí),是否需要反向動(dòng)畫,默認(rèn)是NO
animation.autoreverses = YES;
[shaperLayer addAnimation:animation forKey:nil];
[self.layer addSublayer:shaperLayer];
}
實(shí)現(xiàn)效果:

邊框環(huán)繞二
原理:用到兩個(gè)shaperLayer來實(shí)現(xiàn),利用CAAnimationDelegate代理方法做處理
.h文件
/*第一個(gè)shaperLayer*/
@property (nonatomic,strong) CAShapeLayer *shaperLayer1;
/*第二個(gè)shaperLayer*/
@property (nonatomic,strong) CAShapeLayer *shaperLayer2;
/*第一個(gè)shaperLayer的動(dòng)畫*/
@property (nonatomic,strong) CABasicAnimation *animation1;
/*第二個(gè)shaperLayer的動(dòng)畫*/
@property (nonatomic,strong) CABasicAnimation *animation2;
.m文件
/*無到有的shaper*/
- (CAShapeLayer *)shaperLayer1
{
if(!_shaperLayer1){
_shaperLayer1 = [CAShapeLayer layer];
// shaperLayer1.position = CGPointMake((kWidth-300)/2, (kHeight-200)/2);
_shaperLayer1.strokeColor = [UIColor whiteColor].CGColor;
_shaperLayer1.fillColor = [UIColor clearColor].CGColor;
_shaperLayer1.lineDashPattern = @[@(8)];
// 結(jié)尾處的類型
_shaperLayer1.lineCap = kCALineCapRound;
// 拐角處的類型
_shaperLayer1.lineJoin = kCALineJoinRound;
_shaperLayer1.lineWidth = 5;
}
return _shaperLayer1;
}
/*有到無shaper*/
- (CAShapeLayer *)shaperLayer2
{
if(!_shaperLayer2){
_shaperLayer2 = [CAShapeLayer layer];
// shaperLayer2.position = CGPointMake((kWidth-300)/2, (kHeight-200)/2);
_shaperLayer2.strokeColor = [UIColor whiteColor].CGColor;
_shaperLayer2.fillColor = [UIColor clearColor].CGColor;
_shaperLayer2.lineDashPattern = @[@(8)];
// 結(jié)尾處的類型
_shaperLayer2.lineCap = kCALineCapRound;
// 拐角處的類型
_shaperLayer2.lineJoin = kCALineJoinRound;
_shaperLayer2.lineWidth = 5;
}
return _shaperLayer2;
}
/*注釋*/
- (CABasicAnimation *)animation1
{
if(!_animation1){
_animation1 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
_animation1.duration = 4;
_animation1.fromValue = @(0);
_animation1.toValue = @(1);
_animation1.repeatCount = 1;
_animation1.removedOnCompletion = NO;
_animation1.fillMode = kCAFillModeForwards;
_animation1.delegate = self;
[_animation1 setValue:@"animation1" forKey:@"animation1"];
}
return _animation1;
}
/*注釋*/
- (CABasicAnimation *)animation2
{
if(!_animation2){
_animation2 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
_animation2.fromValue = @(1);
_animation2.toValue = @(0);
_animation2.duration = 4;
_animation2.repeatCount = 1;
// _animation2.autoreverses = YES;
_animation2.removedOnCompletion = NO;
_animation2.fillMode = kCAFillModeBackwards;
_animation2.delegate = self;
[_animation2 setValue:@"animation2" forKey:@"animation2"];
}
return _animation2;
}
- (void)marquee3{
// 創(chuàng)建路徑
UIBezierPath * path1 = [UIBezierPath bezierPath];
[path1 moveToPoint:CGPointMake(20, 200)];
[path1 addLineToPoint:CGPointMake(300, 200)];
[path1 addLineToPoint:CGPointMake(300, 400)];
[path1 addLineToPoint:CGPointMake(20, 400)];
[path1 closePath];
self.shaperLayer1.path = path1.CGPath;
UIBezierPath * path2 = [UIBezierPath bezierPath];
[path2 moveToPoint:CGPointMake(20, 200)];
[path2 addLineToPoint:CGPointMake(20, 400)];
[path2 addLineToPoint:CGPointMake(300, 400)];
[path2 addLineToPoint:CGPointMake(300, 200)];
[path2 closePath];
self.shaperLayer2.path = path2.CGPath;
// 創(chuàng)建動(dòng)畫
[self.shaperLayer1 addAnimation:self.animation1 forKey:@"animation1"];
[self.layer addSublayer:self.shaperLayer1];
[self.layer addSublayer:self.shaperLayer2];
self.shaperLayer2.opacity = 0;
}
//動(dòng)畫開始
- (void)animationDidStart:(CAAnimation *)anim{
}
//動(dòng)畫結(jié)束
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
//判斷是不是第一個(gè)動(dòng)畫
if ([[anim valueForKey:@"animation1"] isEqualToString:@"animation1"]) {
self.shaperLayer1.opacity = 0;
//shaperLayer1刪除掉所有動(dòng)畫
[self.shaperLayer1 removeAnimationForKey:@"animation1"];
[self.shaperLayer2 addAnimation:self.animation2 forKey:@"animation2"];
self.shaperLayer2.opacity = 1;
}else{
self.shaperLayer2.opacity = 0;
//shaperLayer2刪除所有的動(dòng)畫
[self.shaperLayer2 removeAllAnimations];
[self.shaperLayer1 addAnimation:self.animation1 forKey:@"animation1"];
self.shaperLayer1.opacity = 1;
}
}
上述代碼有一段下面的代碼:
[self.shaperLayer2 removeAllAnimations];
一般在動(dòng)畫結(jié)束后,layer會(huì)自動(dòng)刪除掉自己的animation。但是在你設(shè)置了animation的removedOnCompletion屬性為NO的時(shí)候,就需要自己刪除掉layer的animation。removeAllAnimations和removeAnimationForKey不僅有表面的意思刪除掉動(dòng)畫,還有起到暫停動(dòng)畫的效果,在動(dòng)畫過程中實(shí)現(xiàn)這個(gè),會(huì)使動(dòng)畫暫停;
調(diào)用:
[self marquee3];
實(shí)現(xiàn)效果:

這個(gè)動(dòng)畫中間會(huì)跳動(dòng)一下,目前要想實(shí)現(xiàn)這個(gè)效果,沒有想到其他方法,有想法的朋友可以告知下,這里感謝不已。
最后
這里說一個(gè)研究過程中遇到的一個(gè)問題:
問題:animation動(dòng)畫結(jié)束后,會(huì)閃回到最開始狀態(tài),然后消失
解決這個(gè)問題,首先要在創(chuàng)建animation的時(shí)候,設(shè)置兩個(gè)屬性值。分別為:
//這個(gè)屬性表示的是動(dòng)畫結(jié)束后是否回到開始的狀態(tài),默認(rèn)是YES
animation.removedOnCompletion = NO;
//這個(gè)描述的是動(dòng)畫填充方式
animation.fillMode = kCAFillModeForwards;
fillMode 有下面幾個(gè)狀態(tài)值:
kCAFillModeRemoved這個(gè)是默認(rèn)值,也就是說當(dāng)動(dòng)畫開始前和動(dòng)畫結(jié)束后,動(dòng)畫對(duì)layer都沒有影響,動(dòng)畫結(jié)束后,layer會(huì)恢復(fù)到之前的狀態(tài)kCAFillModeForwards當(dāng)動(dòng)畫結(jié)束后,layer會(huì)一直保持著動(dòng)畫最后的狀態(tài)kCAFillModeBackwards在動(dòng)畫開始前,只需要將動(dòng)畫加入了一個(gè)layer,layer便立即進(jìn)入動(dòng)畫的初始狀態(tài)并等待動(dòng)畫開始。kCAFillModeBoth這個(gè)其實(shí)就是上面兩個(gè)的合成,動(dòng)畫加入之后在開始之前,layer便處于動(dòng)畫初始狀態(tài),動(dòng)畫結(jié)束后layer保持動(dòng)畫最后的狀態(tài)
其他的動(dòng)畫效果可以自己嘗試下。
CABasicAnimation的具體應(yīng)用在后續(xù)的CALayer、CAShaperLayer里面都有用到