一、簡介
- CABasicAnimation是
CAPropertyAnimation
的子類, CAPropertyAnimation有一個字符串類型的keyPath
屬性
keyPath內(nèi)容是CALayer的可動畫Animatable屬性
岗照,可動畫屬性可見CAlayer篇我們可以指定CALayer的某個屬性名為
keyPath
村象,并且對CALayer的這個屬性的值進行修改,達到相應的動畫效果攒至。例如:指定keyPath = @"position"厚者,就會修改CALayer的position屬性的值,- > 可以實現(xiàn)平移的動畫效果
屬性說明: fromValue:keyPath相應屬性的初始值迫吐,toValue:keyPath相應屬性的結(jié)束值
因此库菲,初始化好CAPropertyAnimation的子類對象后,必須先設置keyPath(修改的是CALayer的哪個屬性)-> 指明執(zhí)行的是怎樣的動畫(平移/縮放/旋轉(zhuǎn)等)
隨著動畫的進行志膀,在長度為
duration
的持續(xù)時間內(nèi)熙宇,keyPath
相應屬性的值從fromValue
漸漸地變?yōu)?code>toValuekeyPath
內(nèi)容是CALayer
的可動畫Animatable
屬性如果
fillMode=kCAFillModeForwards
同時removedOnComletion=NO
,那么在動畫執(zhí)行完畢后溉浙,圖層會保持顯示動畫執(zhí)行后的狀態(tài)烫止。但在實質(zhì)上,圖層的屬性值還是動畫執(zhí)行前的初始值戳稽,并沒有真正被改變
馆蠕。
屬性說明:
duration
動畫時長fromValue
動畫起始的位置,根據(jù)keyPath的值不一樣惊奇,這里的值也不一樣互躬;比如keyPath是position
的時候,fromValue的值就是[NSValue valueWithCGPoint:<#(CGPoint)#>];
toValue
動畫結(jié)束位置,和fromValue的值一致repeatCount
動畫執(zhí)行次數(shù)Autoreverses
當你設定這個屬性為 YES 時,在它到達目的地之后,動畫的返回到開始的值,代替了直接跳轉(zhuǎn)到 開始的值颂郎。removedOnCompletion
這個是在動畫結(jié)束后吼渡,是否會回到開始的值,默認是YES祖秒。如果設置為NO诞吱,則動畫結(jié)束后,會保持動畫結(jié)束后的形態(tài)竭缝,但layer的相關(guān)屬性值并沒有改變Duration
Duration 這個參數(shù)你已經(jīng)相當熟悉了。它設定開始值到結(jié)束值花費的時間沼瘫。期間會被速度的屬性所影響抬纸。RemovedOnCompletion
這個屬性默認為 YES,那意味著,在指定的時間段完成后,動畫就自動的從層上移除了。這個一般不用耿戚。
假如你想要再次用這個動畫時,你需要設定這個屬性為 NO湿故。這樣的話,下次你在通過-set 方法設定動畫的屬 性時,它將再次使用你的動畫,而非默認的動畫阿趁。
Speed
默認的值為 1.0.這意味著動畫播放按照默認的速度。如果你改變這個值為 2.0,動畫會用 2 倍的速度播放坛猪。 這樣的影響就是使持續(xù)時間減半脖阵。如果你指定的持續(xù)時間為 6 秒,速度為 2.0,動畫就會播放 3 秒鐘---一半的 持續(xù)時間。BeginTime
這個屬性在組動畫中很有用墅茉。它根據(jù)父動畫組的持續(xù)時間,指定了開始播放動畫的時間命黔。默認的是 0.0.組 動畫在下個段落中討論“Animation Grouping”。TimeOffset
如果一個時間偏移量是被設定,動畫不會真正的可見,直到根據(jù)父動畫組中的執(zhí)行時間得到的時間都流逝 了就斤。RepeatCount
默認的是 0,意味著動畫只會播放一次悍募。如果指定一個無限大的重復次數(shù),使用 1e100f。這個不應該和 repeatDration 屬性一塊使用洋机。RepeatDuration
這個屬性指定了動畫應該被重復多久坠宴。動畫會一直重復,直到設定的時間流逝完。它不應該和 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應用:
直線進度條:
/*直線進度條*/
- (CAShapeLayer *)lineAnimationLayer
{
if(!_lineAnimationLayer){
_lineAnimationLayer = [CAShapeLayer layer];
_lineAnimationLayer.strokeColor = [UIColor greenColor].CGColor;
_lineAnimationLayer.lineWidth = 5;
// 設置路徑
UIBezierPath * path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(50, 200)];
[path addLineToPoint:CGPointMake(300, 200)];
_lineAnimationLayer.path = path.CGPath;
/*動畫,keyPath是系統(tǒng)定的關(guān)鍵詞衔肢,可以自己去幫助文檔里面查看*/
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
// animation的動畫時長
animation.duration = 4.0;
// 動畫的其實位置
animation.fromValue = @(0);
// 動畫的結(jié)束位置
animation.toValue = @(1);
// 動畫執(zhí)行次數(shù)
animation.repeatCount = MAXFLOAT;
// 添加動畫并設置key颠通;這個key值是自己定義的
[_lineAnimationLayer addAnimation:animation forKey:@"lineAnimationLayer"];
}
return _lineAnimationLayer;
}
執(zhí)行結(jié)果:
邊框環(huán)繞效果
實現(xiàn)代碼:
/**
* 跑馬燈二(shaperLayer)
*/
-(void)marquee2{
//創(chuàng)建一個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)建動畫路徑
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的動畫和效果和下面的animation動畫效果是一樣的
*/
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.duration = 4;
animation.repeatCount = MAXFLOAT;
animation.fromValue = @(0);
animation.toValue = @(1);
// 這個設置是在一個動畫完成時,是否需要反向動畫膀懈,默認是NO
animation.autoreverses = YES;
[shaperLayer addAnimation:animation forKey:nil];
[self.layer addSublayer:shaperLayer];
}
實現(xiàn)效果:
邊框環(huán)繞二
原理:用到兩個shaperLayer來實現(xiàn)顿锰,利用CAAnimationDelegate代理方法做處理
.h文件
/*第一個shaperLayer*/
@property (nonatomic,strong) CAShapeLayer *shaperLayer1;
/*第二個shaperLayer*/
@property (nonatomic,strong) CAShapeLayer *shaperLayer2;
/*第一個shaperLayer的動畫*/
@property (nonatomic,strong) CABasicAnimation *animation1;
/*第二個shaperLayer的動畫*/
@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)建動畫
[self.shaperLayer1 addAnimation:self.animation1 forKey:@"animation1"];
[self.layer addSublayer:self.shaperLayer1];
[self.layer addSublayer:self.shaperLayer2];
self.shaperLayer2.opacity = 0;
}
//動畫開始
- (void)animationDidStart:(CAAnimation *)anim{
}
//動畫結(jié)束
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
//判斷是不是第一個動畫
if ([[anim valueForKey:@"animation1"] isEqualToString:@"animation1"]) {
self.shaperLayer1.opacity = 0;
//shaperLayer1刪除掉所有動畫
[self.shaperLayer1 removeAnimationForKey:@"animation1"];
[self.shaperLayer2 addAnimation:self.animation2 forKey:@"animation2"];
self.shaperLayer2.opacity = 1;
}else{
self.shaperLayer2.opacity = 0;
//shaperLayer2刪除所有的動畫
[self.shaperLayer2 removeAllAnimations];
[self.shaperLayer1 addAnimation:self.animation1 forKey:@"animation1"];
self.shaperLayer1.opacity = 1;
}
}
上述代碼有一段下面的代碼:
[self.shaperLayer2 removeAllAnimations];
一般在動畫結(jié)束后,layer會自動刪除掉自己的animation启搂。但是在你設置了animation的removedOnCompletion
屬性為NO的時候硼控,就需要自己刪除掉layer的animation。removeAllAnimations
和removeAnimationForKey
不僅有表面的意思刪除掉動畫胳赌,還有起到暫停動畫的效果牢撼,在動畫過程中實現(xiàn)這個,會使動畫暫停疑苫;
調(diào)用:
[self marquee3];
實現(xiàn)效果:
這個動畫中間會跳動一下熏版,目前要想實現(xiàn)這個效果,沒有想到其他方法捍掺,有想法的朋友可以告知下撼短,這里感謝不已。
最后
這里說一個研究過程中遇到的一個問題:
問題:animation動畫結(jié)束后挺勿,會閃回到最開始狀態(tài)曲横,然后消失
解決這個問題,首先要在創(chuàng)建animation的時候,設置兩個屬性值禾嫉。分別為:
//這個屬性表示的是動畫結(jié)束后是否回到開始的狀態(tài)灾杰,默認是YES
animation.removedOnCompletion = NO;
//這個描述的是動畫填充方式
animation.fillMode = kCAFillModeForwards;
fillMode 有下面幾個狀態(tài)值:
kCAFillModeRemoved
這個是默認值,也就是說當動畫開始前和動畫結(jié)束后熙参,動畫對layer都沒有影響艳吠,動畫結(jié)束后,layer會恢復到之前的狀態(tài)kCAFillModeForwards
當動畫結(jié)束后孽椰,layer會一直保持著動畫最后的狀態(tài)kCAFillModeBackwards
在動畫開始前昭娩,只需要將動畫加入了一個layer,layer便立即進入動畫的初始狀態(tài)并等待動畫開始弄屡。kCAFillModeBoth
這個其實就是上面兩個的合成题禀,動畫加入之后在開始之前,layer便處于動畫初始狀態(tài)膀捷,動畫結(jié)束后layer保持動畫最后的狀態(tài)
其他的動畫效果可以自己嘗試下迈嘹。
CABasicAnimation的具體應用在后續(xù)的CALayer、CAShaperLayer里面都有用到